# Problem bei Othello/Reversi



## Sachiko (8. Dez 2012)

Hallo,

ich muss für ein Praktikum das Spiel Othello/Reversi in Java programmieren.
Bin im Grunde damit fertig, bis auf ein Problem, an dem ich schon seit Tagen verzweifelt sitze.
Mein Gegenspieler (KI) soll ein Feld mit dem besten score wählen, wählt aber entweder ein Feld, welches schon besetzt ist oder eins, was für ihn gar nicht erlaubt ist zu setzen (und somit wird sein Zug übersprungen). Ich habe in der Datenstruktur das ganze eigentlich abgeklärt, es scheint aber nicht zu funktionieren.
Ich vermute den Fehler in der "Check"-Methode

OthelloKI

```
package othello;
import java.util.*;

import szte.mi.Move;
import szte.mi.Player;

public class OthelloKI implements Player{
	private OthelloDatenstruktur data;
	private int order;
	private Random rnd;
	private Status me;
	private Status opp;
	private LinkedList<Move> posMoves;
	private HashMap<Move, Integer> possibleMoves;
	int [] counter = new int[2];
	static final int squareScores[][] = new int[][]
    {{50, -1, 5, 2, 2, 5, -1, 50},
    {-1, -10, 1, 1, 1, 1, -10, -1},
    {5, 1, 1, 1, 1, 1, 1, 5},
    {2, 1, 1, 0, 0, 1, 1, 2},
    {2, 1, 1, 0, 0, 1, 1, 2},
    {5, 1, 1, 1, 1, 1, 1, 5},
    {-1, -10, 1, 1, 1, 1, -10, -1},
    {50, -1, 5, 2, 2, 5, -1, 50}};

	@Override
	public void init( int order, long t, Random rnd ) {
		
		this.data = new OthelloDatenstruktur();
		this.order = order;
		this.rnd = rnd;
		this.posMoves = new LinkedList<Move>();
		this.possibleMoves = new HashMap<Move, Integer>();
		
		if(this.order==0){
			
			me=Status.black;
			opp=Status.white;
		}
		else if(this.order==1){
			me=Status.white;
			opp=Status.black;
		}
		else throw new IllegalArgumentException();
		data.setRandom(this.rnd);
	}
	 

	@Override
	public Move nextMove(Move prevMove, long tOpponent, long t ) {
		      data.move(prevMove, opp);
		fillPosMoves();
		
		Move bestMove = null;
		int bestMoveScore = -1000;
		for (Map.Entry<Move, Integer> entry : possibleMoves.entrySet()) {
			if (entry.getValue() > bestMoveScore) {
				bestMove = entry.getKey();
				bestMoveScore = entry.getValue();
			}
		}
		System.out.println("Best: " + bestMove.x + "," + bestMove.y + " score: " + bestMoveScore);
		return bestMove;
	}

   private void fillPosMoves(){
    	for(int i=0; i<8; i++)
    		for(int j=0; j<8; j++)
    			if(data.isValid(new Move(i,j), me))
    			{
    				this.posMoves.add(new Move(i,j));
    				this.possibleMoves.put(new Move(i,j), squareScores[i][j]);
    			}
    }
 
}
```

OthelloDatenstruktur

```
package othello;
import szte.mi.*;

import java.util.*;

enum Status {nil ,black , white}; 

public class OthelloDatenstruktur {
	Status [][] board = new Status[8][8];
	int [] counter = new int[2]; // 0 = schwarz, 1 = weiß
	boolean PassCounter;
	Random rnd;
 
	public OthelloDatenstruktur() {
		clear();
	}
 
	public Status get(int x, int y) {
		return board[x][y];
	}
 
	public void set(Move move, Status player) {
		switch (board[move.x][move.y]) {
			case white:  counter[1]--; break;
			case black:  counter[0]--; break;
		}
		board[move.x][move.y]=player;
		switch (player) {
			case white:  counter[1]++; break;
			case black:  counter[0]++; break;
		}
	}
	
	public void setRandom(Random rnd){
		this.rnd = rnd;
	}
 
	public int getCounter(Status player) {
		return counter[player.ordinal()-1];
	}
 
	public void clear() {
		for (int i = 0 ; i < 8 ; i++)
			for (int j = 0 ; j < 8 ; j++)
				board[i][j]=Status.nil;
		board[3][4]=Status.black;
		board[4][3]=Status.black;
		board[3][3]=Status.white;
		board[4][4]=Status.white;
		counter[0] = 2;
		counter[1] = 2;
		PassCounter = false;
	}
 
	public void println() {
		System.out.print("[");
		for (int i = 0 ; i < 8 ; i++) {
			for (int j = 0 ; j < 8 ; j++)
				System.out.print(board[i][j]+",");
			System.out.println((i == 7? "]":""));
			}
	}
 
	public int move(Move move, Status stat) {
		return checkBoard(move,stat);
	}
	
 
	public boolean gameEnd() {
		return counter[0]+counter[1]==64;
	}
 
	private int Check(Move move, int incx, int incy, Status stat , boolean set)  {
		Status opponent;
		int x=move.x;
		int y=move.y;
		if (stat == Status.black) opponent=Status.white; else opponent=Status.black;
		int n_inc=0;
		
		if (board[x][y] != Status.nil) {
			return 0;
		}
		if (board[x][y] == board[3][4] || board[x][y] == board[4][3] || board[x][y] == board[3][3] || board[x][y] == board[4][4]){
            return 0;
		}
			
		x+=incx; y+=incy;

		while ((x<8) && (x>=0) && (y<8) && (y>=0) && (board[x][y]==opponent)) {
			x+=incx; y+=incy;
			n_inc++;
		}
		if ((n_inc != 0) && (x<8) && (x>=0) && (y<8) && (y>=0) && (board[x][y]==stat)) {
			 if (set)
				for (int j = 1 ; j <= n_inc ; j++) {
				x-=incx; y-=incy;
				 set(new Move(x,y),stat);
			 }
			return n_inc;
		}
		else return 0;
	}
 
	public int checkBoard(Move move, Status stat) {
	
		int y=Check(move,1,0,stat,true);
		
		y+=Check(move,-1,0,stat,true);
		
		y+=Check(move,0,1,stat,true);
		
		y+=Check(move,0,-1,stat,true);
		
		y+=Check(move,1,1,stat,true);
		y+=Check(move,-1,1,stat,true);
		y+=Check(move,1,-1,stat,true);
		y+=Check(move,-1,-1,stat,true);
		if (y != 0) set(move,stat);
		return y;
	}
 
	public boolean isValid(Move move, Status stat) {
		
		if (Check(move,1,0,stat,false) != 0) return true;
		
		if (Check(move,-1,0,stat,false) != 0) return true;
		
		if (Check(move,0,1,stat,false) != 0) return true;
		
		if (Check(move,0,-1,stat,false) != 0) return true;
		 
		if (Check(move,1,1,stat,false) != 0) return true;
		if (Check(move,-1,1,stat,false) != 0) return true;
		if (Check(move,1,-1,stat,false) != 0) return true;
		if (Check(move,-1,-1,stat,false) != 0) return true;
		return false;
	}
	public boolean userCanMove(Status player)  {
		for (int i = 0 ; i < 8 ; i++)
			for (int j = 0 ; j < 8 ; j++)
			  if ((board[i][j] == Status.nil) && isValid(new Move(i,j),player)) return true;
		return false;
		}
	
}
```

Vielen lieben Dank für jede Hilfe.


----------



## TKausL (8. Dez 2012)

Leerst du possibleMoves auch irgendwann mal?


----------



## Sachiko (8. Dez 2012)

Wie würde das denn im Code funktionieren?
Komme damit nicht ganz zurecht.

Danke ^^


----------



## TKausL (8. Dez 2012)

Dann guck dir mal die Java-API zur HashMap an, da steht die Methode drin die du zum leeren brauchst


----------



## Sachiko (8. Dez 2012)

Ich würd es dann mit clean() leeren.
Wie kriege ich es dann hin, dass es beim nächstes Zug wieder mit den neuen möglichen Zügen aufgefüllt wird?


----------



## TKausL (8. Dez 2012)

Ich würde einfach am Anfang der fillPosMoves()-Methode, also dort wo die Liste gefüllt wird leeren.


----------



## Sachiko (9. Dez 2012)

Vielen Dank für den Vorschlag.
Leider hat sich nichts geändert.


----------



## TKausL (9. Dez 2012)

Dann Spiel doch mal mit dem Debugger rum und guck warum/ob falsche Züge in die Liste reingepackt werden.


----------

