好吧,所以我一直在關注在Java中的Connect4本教程,我試圖修改它,以適應我已經有的東西,適合libgdx。實施後,我有一些奇怪的問題。Connect4在Libgdx
問題1:在我第一步之後,計算機用他的芯片填滿了整個底部行,然後進行第一步。
問題2:計算機沒有顯示任何A.I.並從第一列和第一列開始,並在那裏放置一個芯片。電腦將繼續遵循這種模式。
問題3:如果我贏得了比賽,但是當計算機贏了時,我的獲獎檢查員不再意識到。當我第一次設計遊戲時,我開始讓計算機隨機放置芯片(用於測試),而我的獲獎檢查人員則爲計算機和我自己工作。
我跟着這篇文章是在這裏:Connect4 in Java
這裏是我的代碼。
ConnectFour.java
package com.comp452.tme31;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class ConnectFour extends ApplicationAdapter implements InputProcessor {
// Create final ints for number of columns and rows in game.
protected final static int COLUMNS = 7;
protected final static int ROWS = 6;
protected final static int TILESIZE = 64;
// Create boolean to determine if player can take a turn.
protected boolean playersTurn = true;
// Create boolean for gameover.
protected boolean gameOver = false;
// Create boolean for winners.
private boolean winner = false;
// Sprite batch for texture drawing.
SpriteBatch batch;
// Create textures to represent board and player pieces.
Texture drawingTile, empty, player, computer;
// Create 2D array to hold game board.
private final static int[][] gameBoard = new int[COLUMNS][ROWS];
public static int[][] getGameBoard() {
return gameBoard;
}
// Create variables to display status message.
BitmapFont mainStatusDisplay;
public static String mainStatusString;
public static String winningString;
// Create and set max depth for tree search
private final int MAX_DEPTH = 4;
// Create win, loss and nothing for zero sum game.
private final float WIN = 1f;
private final float LOSE = -1f;
private final float TIE = 0f;
@Override
public void create() {
batch = new SpriteBatch();
empty = new Texture("empty.jpg");
player = new Texture("player.jpg");
computer = new Texture("computer.jpg");
Gdx.input.setInputProcessor(this);
// Initialize display for status messages.
mainStatusDisplay = new BitmapFont();
mainStatusString = "Player's Turn";
winningString = "";
}
@Override
public void render() {
update();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
drawBoard();
mainStatusDisplay.setColor(Color.YELLOW);
mainStatusDisplay.draw(batch, mainStatusString, 32, 416);
batch.end();
}
public void drawBoard() {
for (int i = 0; i < COLUMNS; i ++) {
for (int j = 0; j < ROWS; j++) {
if (gameBoard[i][j] == 0) {
drawingTile = empty;
}
else if (gameBoard[i][j] == 1) {
drawingTile = player;
}
else if (gameBoard[i][j] == 2) {
drawingTile = computer;
}
batch.draw(drawingTile, i * 64, j * 64);
}
}
}
// Method update handles updates to game logic.
public void update() {
// If it's gameover, end the game.
if (gameOver) {
// Set players turn to true to prevent computer from taking another turn.
playersTurn = true;
// Set status message to winning message;
mainStatusString = winningString;
// Disable input processor to prevent player from taking another turn.
Gdx.input.setInputProcessor(null);
}
// If it's not players turn, call computersTurn.
else if (!playersTurn) {
mainStatusString = "Computer's Turn";
computersTurn();
}
if (checkForWin(1) && checkForWin(2)) {
gameOver = true;
}
}
public void computersTurn() {
double maxScore = 2. * Integer.MIN_VALUE;
int xValue = 0;
// Search the gameboard and find the best move.
for (int x = 0; x < COLUMNS; x++) {
// If x column is a value move...
if (canMove(x)) {
// Set score of move from function.
double score = moveScore(x);
// If score is greater than max score...
if (score > maxScore) {
// Set score to max score and xValue to column.
maxScore = score;
xValue = x;
// If the score is a win, break from loop.
if (score == WIN) {
break;
}
}
}
}
// Set the piece for player at column as x.
setPiece(2, xValue);
// Set players turn and string status.
playersTurn = true;
mainStatusString = "Player's Turn";
}
// Method moveScore determines the value of a move and returns it.
public double moveScore(int xValue) {
// Set the piece in place.
setPiece(2, xValue);
// Get the score and check it's value with alpha beta pruning.
double score = alphaBetaPrune(MAX_DEPTH, Integer.MIN_VALUE, Integer.MAX_VALUE, 1);
// Remove the piece.
takeAwayPiece(xValue);
return score;
}
public double alphaBetaPrune(int depth, double alpha, double beta, int whoPlayed) {
winner = checkForWin(1) || checkForWin(2);
// If we've reached the max depth of the tree or there is a winner...
if (depth == 0 || winner) {
double score;
// If there is a winner...
if (winner) {
// If player is the winner...
if (checkForWin(1)) {
// Set a losing score (Computer does not want player to win).
score = LOSE;
}
// Else this is a win for the computer...
else {
// Set score to a win.
score = WIN;
}
}
// Otherwise there is no winner...
else {
// Set score to TIE (0).
score = TIE;
}
// Return score and remove depth level.
return score/(MAX_DEPTH - depth +1);
}
// If computer is making the move...
if (whoPlayed == 2) {
// Iterate through gameboard.
for (int x = 0; x < COLUMNS; x++) {
// Check and see if next move can be made.
if (canMove(x)) {
// Make move for computer to x.
setPiece(2, x);
// Set alpha equal to return from recursion step minus one depth level.
alpha = Math.max(alpha, alphaBetaPrune(depth - 1, alpha, beta, 1));
// Remove piece.
takeAwayPiece(x);
// Check returned alpha against beta and break from loop if beta is less than alpha.
if (beta <= alpha) {
break;
}
}
}
// We're here if alpha is larger and we didn't break from loop.
return alpha;
}
// Else if player is making move...
else {
// Iterate through gameboard.
for (int x = 0; x < COLUMNS; x++) {
// Check and see if next move can be made.
if (canMove(x)) {
// Make move for player to x.
setPiece(1, x);
// Set beta equal to return from recursion step minus one depth level for beta.
beta = Math.min(beta, alphaBetaPrune(depth - 1, alpha, beta, 2));
// Remove piece.
takeAwayPiece(x);
// Check returned alpha against beta and break from loop if beta is less than alpha.
if (beta <= alpha) {
break;
}
}
}
// We're here if alpha is larger than beta and we didn't break from loop.
return beta;
}
}
// Method setPiece takes two int values as parameters and places a piece on the game board.
public void setPiece(int whoPlayed, int xValue) {
// For loop to iterate through each row.
for (int i = 0; i < ROWS; i++) {
// If row is empty...
if (gameBoard[xValue][i] == 0) {
// Place piece on the board.
gameBoard[xValue][i] = whoPlayed;
break;
}
}
}
// Method takeAwayPiece takes two int values as parameters and removes a piece from the board.
public void takeAwayPiece(int xValue) {
// For loop to iterate through each row.
for (int i = ROWS - 1; i > 0; i--) {
// If row contains a piece..
if (gameBoard[xValue][i] != 0) {
// Remove piece.
gameBoard[xValue][i] = 0;
break;
}
}
}
// Method to determine if a move is valid
public boolean canMove(int xValue) {
// If the top spot in the given column is 0, return true.
return (gameBoard[xValue][ROWS-1] == 0);
}
// Method checkForWin takes a flag and checks to see if that player has won the game.
public boolean checkForWin(int whoPlayed) {
// Create counter to check for 4 in a row.
int win = 0;
// Iterate through gameboard and count pieces in a row.
for (int y = 0; y < ROWS; y++) {
for (int x = 0; x < COLUMNS; x++) {
// If piece is player who is checking, increment counter.
if (gameBoard[x][y] == whoPlayed) {
win++;
}
// Not in a row, set counter to 0.
else {
win = 0;
}
if (win == 4) {
break;
}
}
// If win counter is 4, winner.
if (win == 4) {
winningString = "Horizontal Win for Player " + whoPlayed;
return true;
}
// Else, reset win counter and check next column.
else {
win = 0;
}
}
// Iterate through gameboard and count pieces in a column.
for (int x = 0; x < COLUMNS; x++) {
for (int y = 0; y < ROWS; y++) {
// If piece is player who is checking, increment counter.
if (gameBoard[x][y] == whoPlayed) {
win++;
}
// Not in a row, set counter to 0.
else {
win = 0;
}
if (win == 4) {
break;
}
}
// If win counter is 4, player won.
if (win == 4) {
winningString = "Vertical Win for Player " + whoPlayed;
return true;
}
// Else, reset win counter and check next column.
else {
win = 0;
}
}
// Iterate through gameboard and count pieces in a diagonal row, left to right.
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 2; y++) {
// If piece is player who is checking, check next piece diagonally.
if (gameBoard[x][y] == whoPlayed) {
// Then check next diagonal piece.
if (gameBoard[x+1][y+1] == whoPlayed) {
// Then check next diagonal piece.
if (gameBoard[x+2][y+2] == whoPlayed) {
// Then check last diagonal piece.
if (gameBoard[x+3][y+3] == whoPlayed) {
// Set winning message to player won and set gameover flag.
winningString = "Diagonal Win (LR) for Player " + whoPlayed;
// Exit function.
return true;
}
}
}
}
}
}
// Iterate through gameboard and count pieces in a diagonal row, right to left.
for (int x = 3; x < COLUMNS; x++) {
for (int y = 0; y < 2; y++) {
// If piece is player who is checking, check next piece diagonally.
if (gameBoard[x][y] == whoPlayed) {
// Then check next diagonal piece.
if (gameBoard[x-1][y+1] == whoPlayed) {
// Then check next diagonal piece.
if (gameBoard[x-2][y+2] == whoPlayed) {
// Then check last diagonal piece.
if (gameBoard[x-3][y+3] == whoPlayed) {
// Set winning message to player won and set gameover flag.
winningString = "Diagonal Win (RL) for Player " + whoPlayed;
// Exit function.
return true;
}
}
}
}
}
}
// Iterate through gameboard and if no 0 slots remain, game is a tie.
for (int x = 0; x < COLUMNS; x++) {
for (int y = 0; y < ROWS; y++) {
// If a 0 slot remains, return.
if (gameBoard[x][y] == 0) {
return false;
}
}
}
// If we're here, then there was no winners and no slots left.
winningString = "Tie Game";
return false;
}
@Override
public boolean touchDown(int x, int y, int pointer, int button) {
if (playersTurn) {
if (button == Input.Buttons.LEFT) {
if (canMove(x/TILESIZE)) {
setPiece(1, x/TILESIZE);
playersTurn = false;
return true;
}
}
}
return false;
}
@Override
public boolean touchUp(int i, int i1, int i2, int i3) {
return false;
}
@Override
public boolean touchDragged(int i, int i1, int i2) {
return false;
}
@Override
public boolean mouseMoved(int i, int i1) {
return false;
}
@Override
public boolean scrolled(int i) {
return false;
}
@Override
public boolean keyDown(int i) {
return false;
}
@Override
public boolean keyUp(int i) {
return false;
}
@Override
public boolean keyTyped(char c) {
return false;
}
}
謝謝!
我能夠追蹤win checker error的來源。在我的更新方法中,我用一個&&符號來檢查,這意味着如果布爾值失敗,表達式失敗,並且由於玩家和計算機不能同時獲勝,它總是會返回false。我將它改爲OR(||),然後突然,win checker工作,現在是A.I.也適用。唯一的問題仍然是計算機從一開始就放置整行棋子的第一個問題。 – 2015-04-04 02:13:27