Reputation: 2421
I have a tic tac toe board made of buttons. Each button is linked to the method that initiated the logic. The problem I'm having is that when the human player (noughts) plays their turn, the logic is skipping that turn, running the AIs turn and then only going back to the human player, who this time around is working as expected.
On the click, the button is question should have setText
method called and marked with either a 'O' for the human player, or 'X' for the AI.
Following this the button is set to inactive and the array that tracks the board changes.
I am printing to the logs and from what I can see, the human users clicks are what are triggering the AIs moved, rather than this being done automatically. But I can't tell why this is happening. I assume there is a flaw in my logic but I can't pick out what the issue is. EDIT: It works fine for the first human click, it is the ones after that that are the problem.
Code:
package com.example.richardcurteis.connect3;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import java.util.Random;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
boolean noughtsTurn;
ArrayList board;
Players player;
int aiPickedButton;
int buttonPressed;
int targetIndex;
public void receiveClick(View view) {
String takeButton = String.valueOf(view.getTag());
buttonPressed = Integer.parseInt(takeButton);
playNow(view);
//checkForWin; Check winning conditions. Not yet implemented
}
public void playNow(View view) {
if (noughtsTurn) {
System.out.println("Player picked: " + buttonPressed);
playerClick(view);
} else {
if (aiValidPick()) {
playerClick(view);
} else {
playNow(view);
}
}
}
public void setTurn(boolean trueOrFalse) {
if (trueOrFalse) {
noughtsTurn = false;
} else {
noughtsTurn = true;
}
}
public void playerClick(View view) {
Button B;
int boardSetIndex;
int boardSetValue;
if (view instanceof Button) {
B = (Button) view;
if ( noughtsTurn ) {
B.setText(player.noughtsPlayer());
} else {
B = aiPlayerPick();
System.out.println("AI picked: " + targetIndex);
B.setText(player.crossesPlayer());
}
board.set(boardSetIndex(), boardSetValue());
System.out.println("Board: " + board);
B.setEnabled(false);
setTurn(noughtsTurn);
}
}
public int boardSetIndex() {
int index;
if (noughtsTurn) {
index = buttonPressed;
} else {
index = targetIndex;
}
return index;
}
public int boardSetValue() {
int value;
if (noughtsTurn) {
value = player.humanTurnValue();
} else {
value = player.aiTurnValue();
}
return value;
}
public Integer randomButtonPick() {
Random randomNumber = new Random();
int randomInt = randomNumber.nextInt(board.size());
return randomInt;
}
public boolean aiValidPick() {
aiPickedButton = randomButtonPick();
if (board.get(aiPickedButton).equals(player.boardArrayDefaultValue())
&& !board.get(aiPickedButton).equals(player.humanTurnValue())
&& !board.get(aiPickedButton).equals(player.aiTurnValue())){
return true;
} else {
return false;
}
}
public Button aiPlayerPick() {
Button btn = null;
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
for (int rowIndex = 0; rowIndex < tableLayout.getChildCount(); rowIndex++) {
View tableLayoutChild = tableLayout.getChildAt(rowIndex);
if (tableLayoutChild instanceof TableRow) {
for (int i = 0; i < ((ViewGroup) tableLayoutChild).getChildCount(); i++) {
View view = ((ViewGroup) tableLayoutChild).getChildAt(i);
String targetButton = String.valueOf(aiPickedButton);
if (view instanceof Button && view.getTag().equals(targetButton) ) {
targetIndex = Integer.parseInt(targetButton);
View btn_v = view.findViewWithTag(targetButton);
btn = (Button) btn_v;
break;
}
}
}
}
return btn;
}
public class Players {
public String noughtsPlayer() { return "O"; }
public String crossesPlayer() { return "X"; }
//public String blankButton() { return ""; }
public int humanTurnValue() { return 0;}
public int aiTurnValue() { return 1;}
public int boardArrayDefaultValue() { return 2;}
}
public int getBoardSize() {
int buttonCount = 0;
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
for (int rowIndex = 0; rowIndex < tableLayout.getChildCount(); rowIndex++) {
View tableLayoutChild = tableLayout.getChildAt(rowIndex);
if (tableLayoutChild instanceof TableRow) {
for (int i = 0; i < ((ViewGroup) tableLayoutChild).getChildCount(); i++) {
View view = ((ViewGroup) tableLayoutChild).getChildAt(i);
if (view instanceof Button) {
buttonCount++;
}
}
}
}
return buttonCount;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
noughtsTurn = true;
player = new Players();
board = new ArrayList();
int boardSize = getBoardSize();
for (int boardIndex = 0; boardIndex < boardSize; boardIndex++) {
board.add(player.boardArrayDefaultValue());
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.example.richardcurteis.connect3.MainActivity"
tools:showIn="@layout/activity_main"
android:background="#070000">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="false"
android:layout_alignParentEnd="false"
android:layout_alignParentStart="false"
android:layout_centerInParent="true"
android:id="@+id/tableLayout"
android:background="#000000">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton1"
android:layout_column="4"
android:onClick="receiveClick"
android:tag="0" />
android:nestedScrollingEnabled="false" />
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton2"
android:layout_column="12"
android:onClick="receiveClick"
android:tag="1" />
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton3"
android:layout_column="19"
android:onClick="receiveClick"
android:tag="2" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton4"
android:layout_column="4"
android:onClick="receiveClick"
android:tag="3"/>
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton5"
android:layout_column="12"
android:onClick="receiveClick"
android:tag="4"/>
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton6"
android:layout_column="19"
android:onClick="receiveClick"
android:tag="5"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"></TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton7"
android:layout_column="4"
android:onClick="receiveClick"
android:tag="6"/>
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton8"
android:layout_column="12"
android:onClick="receiveClick"
android:tag="7"/>
<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/gridButton9"
android:layout_column="19"
android:onClick="receiveClick"
android:tag="8" />
</TableRow>
</TableLayout>
<Button
android:layout_width="200dp"
android:layout_height="120dp"
android:text="New Game"
android:id="@+id/newGameButton"
android:layout_below="@+id/tableLayout"
android:layout_centerHorizontal="true"
android:layout_marginTop="61dp" />
</RelativeLayout>
Upvotes: 1
Views: 509
Reputation: 2421
Ok, so here is the final solution I came to for this issue.
I kept the same logic but separated the human and AI turns into separate methods with the AI still basing it's turn on the noughtsTurn
method.
Code:
public void receiveClick(View view) {
String takeButton = String.valueOf(view.getTag());
buttonPressed = Integer.parseInt(takeButton);
humanPlayerTurn(view);
aiPlayerTurn(view);
}
public void humanPlayerTurn(View view) {
if (noughtsTurn) {
System.out.println("Player picked: " + buttonPressed);
playerClick(view);
}
}
public void aiPlayerTurn(View view) {
if (aiValidPick()) {
playerClick(view);
} else {
aiPlayerTurn(view);
}
}
Upvotes: 0
Reputation: 36
The issue is not in your logic. The issue is how it is implemented.
You currently have a step-by-step logic system in place where each step in the logic is triggered by the receiveClick(View) method. The problem is that there is no automatic triggering of the AI turn.
You need to add some sort of logic to the end of playerClick(View) so that if the player just took their turn it reruns the logic for the AI turn.
Example:
public void playerClick(View view) {
Button B;
int boardSetIndex;
int boardSetValue;
if (view instanceof Button) {
B = (Button) view;
if ( noughtsTurn ) {
B.setText(player.noughtsPlayer());
} else {
B = aiPlayerPick();
System.out.println("AI picked: " + targetIndex);
B.setText(player.crossesPlayer());
}
board.set(boardSetIndex(), boardSetValue());
System.out.println("Board: " + board);
B.setEnabled(false);
//
if(setTurn(noughtsTurn) == false){
playNow(findViewByTag(randomButtonPick()))
}
//
}
}
In the above example there are some critical things missing like checking that the randomButtonPick() is not already occupied and the fact that setTurn(boolean) returns void and not a boolean. You just need some way of checking if the player just took a turn and, if so, have the AI take a turn.
Upvotes: 1