Im making this console game and the way im doing it is printing chars to the console from a 3 dimentional array called map. Which is assigned using the chars of the monsters, characters and background. The problem is i have been able to assign to the map array and print of successfully the char taken a monster class. But for some reason the derived character class objects aren't having their chars printed.
I am confident this is not an access issue cause there are no compiling errors and when the program runs there are empty gaps on the row(not the exact index but the right row index) that the characters are assigned to.
Here is the code that assigns it:
void game::assignScreen() {
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 40; col++) {
if (col == 0 || col == 39) {
map[row][col] = (char) 124;
} else if (row == 0 || row == 19) {
map[row][col] = (char) 95;
} else {
map[row][col] = (char) 46;
}
}
}
switch (difficulty) {
case 1:
for (int i=0; i <2; i++){
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
case 2:
if (difficulty == 2) {
for (int i = 0; i <4; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
}
map[elfPlayer.getPos(true)][elfPlayer.getPos(false)] = elfPlayer.getSymbol();
map[guardPlayer.getPos(true)][guardPlayer.getPos(false)] = guardPlayer.getSymbol();
map[knightPlayer.getPos(true)][knightPlayer.getPos(false)] = knightPlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
break;
case 3:
for (int i = 0; i <6; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
case 4:
if (difficulty == 4) {
for (int i = 0; i <9; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
}
map[elfPlayer.getPos(true)][elfPlayer.getPos(false)] = elfPlayer.getSymbol();
map[guardPlayer.getPos(true)][guardPlayer.getPos(false)] = guardPlayer.getSymbol();
map[knightPlayer.getPos(true)][knightPlayer.getPos(false)] = knightPlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
break;
}
}
And this prints it
void game::printScreen(string msg) {
clearScreen();
cout << msg;
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 40; col++) {
if (map[row][col] == 'E' || map[row][col] == 'G' || map[row][col] == 'K' ||
map[row][col] == 'R' || map[row][col] == 'W') {
if (getPlayer(map[row][col]).getStatus() == 1) {
changeColor(14, false);
cout << map[row][col];
changeColor(15, false);
} else if (getPlayer(map[row][col]).getStatus() == 2 || getPlayer(map[row][col]).getStatus() == 3) {
changeColor(4, false);
cout << map[row][col];
changeColor(15, false);
}
} else {
cout << map[row][col];
}
}
cout << endl;
}
}
getPlayer is a function that takes the currently saved/selected char and returns the object it belongs to
position
int character::getPos(bool getX) {
if (getX) {
return xPos;
} else {
return yPos;
}
}
returns char
char character::getSymbol() {
return symbol;
}
header file
class character
{
public:
character();
~character();
string getName();
char getSymbol();
int getStatus();
int getPos(bool);
void setPos(int, int);
void setStatus(bool, bool);
protected:
string className;
char symbol;
private:
int xPos;
int yPos;
};
from game header file
monster *enemy[21];
elf elfPlayer;
guard guardPlayer;
knight knightPlayer;
rogue roguePlayer;
wizard wizardPlayer;
printScreen(elfPlayer.getName());
cout << elfPlayer.getSymbol();
I tested whether the postions for the objects can be printed, it's working for *enemy[], the derived classes look fine. I really have no idea why it's not printing right. Maybe im making a stupid mistake id just like some insight.
What happens when the map is printed, the bottom right empty area is meant to be full of chars
I turns out it was just a very silly mistake on my part. Thanks to Simon Kraemer for finding the problem.
I just added another else to print out stuff to the character if statement inside of the printScreen method.
Btw, what does it matter if i have a get positon function like that, it uses less space and is quicker to use. Also this is not a group project so confusion is not an issue (if i was in a group perhaps id change it).
Related
Hi I am attempting to create a chess board to reintroduce myself to c++. I am having trouble with adding a member function to my array that the chess board is located in.
I believe I am structuring the problem incorrectly.
.cpp file:
#include "spaces.h"
#include <iostream>
char board::spaceLetter() {
return letter;
}
char board::spaceNumber() {
return number;
}
string board::getColor(board a) {
if (a.color() == true) //Also an error but not a big deal
return "black";
else
return "white";
}
void board::printBoard(board a[][8]) {
for (int i = 1; i <= 8; i++) {
for (int j = 1; j <= 8; j++) {
if (a[i][j].color() == true) { //This is where my problem is
cout << "w";
}
else
cout << "b";
}
cout << endl;
}
}
Header .h
#pragma once
#include <iostream>
using namespace std;
class board {
private:
int boardSpace[8][8];
bool color;
char number;
char letter;
public:
board(){
for (int i = 1; i <= 8; i++) {
for (int j = 1; j <= 8; j++) {
if (((i + j) % 2) == 0)
color = true; //black space
else
color = false;
}
}
}
char spaceLetter();
char spaceNumber();
string getColor(board);
void printBoard(board a[][8]);
};
Thank you!
Welcome to SO.
if (a.color() == true) //Also an error but not a big deal
color is not a function. It is a member variable. Remove the () from color().
Same mistake here:
if (a[i][j].color() == true)
Try running the code here and see if it works for you: https://rextester.com/GRG48268
I'm new to C++ and I'm trying to figure out why I get two "*" symbols in my game board when I'm moving around. The game is supposed to be about avoiding the troll (#). But I am getting duplicate # and * symbols, and I can't figure out why. It seems that the problem is either in one of the for loops or in the posX or posY variables, which I found out by commenting out segments of the code:
#include <iostream>
#include <string>
using namespace std;
void ClearScreen()
{
cout << string(100, '\n');
}
main()
{
int size_arrx = 10;
int size_arry = 20;
int posX = 0;
int posY = 0;
int trollX = size_arrx - 1;
int trollY = size_arry - 1;
char a[size_arry][size_arrx];
bool Alive = true;
char player = '*';
char troll = '#';
while (Alive == true) {
ClearScreen();
for (int i = 0; i<size_arrx; i++)
{
for (int j = 0; j<size_arry; j++)
{
a[i][j] = 'x';
}
}
for (int i = 0; i<size_arrx; i++)
{
for (int j = 0; j<size_arry; j++)
{
a[posX][posY] = player;
a[trollX][trollY] = troll;
cout << a[i][j];
if (posX< 0) {
a[posX = 0][posY] = player;
cout << a[i][j];
}
else if (posY< 0) {
a[posX][posY = 0] = player;
cout << a[i][j];
}
else if (posY > size_arry - 1) {
a[posX][posY = size_arry - 1] = player;
cout << a[i][j];
}
else if (posX > size_arrx - 1) {
a[posX = size_arrx - 1][posY] = player;
cout << a[i][j];
}
}
cout << endl;
}
char dir;
cin >> dir;
if (dir == 'w') {
trollX++;
posX--;
}
if (dir == 's') {
trollX--;
posX++;
}
if (dir == 'd') {
trollY--;
posY++;
}
if (dir == 'a') {
trollY++;
posY--;
}
}
if ((trollX == posX) && (trollY == posY)) {
Alive == false;
}
}
The result looks like this. I only want one *. The * can move perfectly fine, but a duplicate * follows the original * but 11 X's away.
xxxxxxxxxx*xxxxxxxxx <---- This is a duplicate *
*xxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxx#
xxxxxxxxx#xxxxxxxxxx <---- This is a duplicate #
Thanks in advance if you can help me
for (int i=0;i<size_arrx;i++){
for (int j=0;j<size_arry;j++){
a[i][j]='x';
}
}
a[posX][posY]=player;
a[trollX][trollY]=troll;
for (int i=0;i<size_arrx;i++){
for (int j=0;j<size_arry;j++){
cout << a[i][j];
Using this code gave the same error. I'm interpreting this as a[i][j]='x' populates all positions of a[][] with X's. a[posX][posY]=player; overwrites the position of the player with an * (could be x 2 y 5 for example) and then the board gets printed by cout << a[i][j];. I don't understand how a duplicate symbol gets thrown in there.
Let's simplify your program.
Initialize the board outside of the while loop.
There should be no reason to keep initializing it:
for (unsigned int row = 0; row < size_arry; ++row)
{
std::fill(&a[row][0], &a[row][size_arrx], 'x'); // Fill a row.
}
Printing the board should be simple:
for (unsigned int row = 0; row < size_arry; ++row)
{
for (unsigned int column = 0; column < size_arrx; ++column)
{
cout << a[row][column];
}
cout << '\n';
}
Now the character logic.
Every character has a position, row and column, of where it is. To ease restoration, every character should have a previous position also.
struct Position
{
unsigned int row;
unsigned int column;
};
Sorry about that code, the fingers and keyboard are not cooperating.
To move a character to a valid new position, you have to restore the previous position:
unsigned int player_now_x;
unsigned int player_now_y;
unsigned int player_prev_x;
unsigned int player_prev_y;
//...
a[player_prev_y][player_prev_x] = 'x';
a[player_now_y][player_now_y] = player;
For processing single letter commands, a switch statement may be more readable:
// Update previous position.
player_prev_x = player_now_x;
player_prev_y = player_now_y;
switch (dir)
{
case 'd':
if (player_now_y < size_arry)
{
++player_now_y;
}
break;
case 's':
if (player_now_x < size_arrx)
{
++player_now_x;
}
break;
// ...
}
Simplifications.
You can print the board with one cout if you add an extra column. The ending column of each row (except the last) will have a line ending character, '\n'. The last column of the last row will have a termination character, '\0'.
struct Board
{
void set_player(const Position& pos, char player_token)
{
a[pos.x][pos.y] = player_token;
}
void move_player(const Position& new_position,
const Position& previous_position,
char player_token)
{
set_player(previous_position, 'x');
set_player(new_position, player_token);
}
void print()
{
std::cout << &a[0][0] << "\n";
}
Board()
{
for (unsigned int y = 0; y < size_arry; ++y)
{
std::fill(&a[y][0], &a[y][size_arrx], 'x');
a[y][size_arrx - 1] = '\n';
}
a[size_arry - 1][size_arrx - 1] = '\0';
}
};
//...
Board b;
Position player_now;
Position player_prev;
const char player_token = '*';
//...
switch (dir)
{
case 'd':
if (player_now.y < size_arry)
{
++player_now.y;
}
//...
}
b.move_player(player_now, player_previous, player_token);
Sorry again, for the above code fragment, it's the fingers typing out what they want.
I made a sudoku solver, but need to be able to take inputs in to set the puzzle before being solved. The input will be in a 1,2,,,,3,4 format where a space between 2 commas indicates a blank space (and obviously this will all be done row by row). I also have my code set up to use blank spots as 0s and would like to know how to read the input, parse each number into an int and also parse blanks as 0s.
As stated above, this is for C++ and is in Visual Studio Express 2013.
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "cstdlib"
#include "stdio.h"
#include "iostream"
#include "sstream"
using namespace std;
//find the first empty slot on the puzzle
bool FindEmptyCell(int puzzle[9][9], int &row, int &colm);
//check if the inserted number is a legal move
bool isLegal(int puzzle[9][9], int row, int colm, int num);
//being solving through backtracking
bool solve(int puzzle[9][9])
{
int row, colm; //establish rows and columns
//check if there are any empty slots
if (!FindEmptyCell(puzzle, row, colm))
{
return true; //puzzle is assumed solved
}
else
{
//start backtracking with the number 1
for (int i = 1; i<10; i++)
{
if (isLegal(puzzle, row, colm, i))
{
puzzle[row][colm] = i;
if (solve(puzzle) == true)
{
return true; //if there is no problem with the first number, move on
}
else
{
puzzle[row][colm] = 0;
}
}
}
}
return false; //start recursion to try next number
}
//check if the move is legal in the 3x3 square, needs the row and column of the square
bool CheckSquare(int puzzle[9][9], int sqRow, int sqColm, int chkNum)
{
for (int row = 0; row < 3; row++)
{
for (int colm = 0; colm < 3; colm++)
{
if (puzzle[row + sqRow][colm + sqColm] == chkNum)
{
return true; //the number is there and the move is illegal
}
}
}
return false; //the number is not there and the move is assumed legal
}
//check if the move is legal in the row
bool CheckRow(int puzzle[9][9], int row, int chkNum)
{
for (int colm = 0; colm <9; colm++)
{
if (puzzle[row][colm] == chkNum)
{
return true; //the number is there and the move is illegal
}
}
return false; // the number is not there and the move is assumed legal
}
//check if the move is legal in the column
bool CheckColm(int puzzle[9][9], int colm, int chkNum)
{
for (int row = 0; row <9; row++)
{
if (puzzle[row][colm] == chkNum)
{
return true; //the number is there and the move is illegal
}
}
return false; // the number is not there and the move is assumed legal
}
//definition of finding empty slot method
bool FindEmptyCell(int puzzle[9][9], int &row, int &colm)
{
for (colm = 0; colm < 9; colm++)
{
for (row = 0; row < 9; row++)
{
if (puzzle[row][colm] == 0)
{
return true;
}
}
}
return false;
}
//definition of is legal method
bool isLegal(int p[9][9], int r, int c, int cN)
{
if (CheckRow(p, r, cN) == false)
{
if (CheckColm(p, c, cN) == false)
{
if (CheckSquare(p, r - r % 3, c - c % 3, cN) == false) //use % to find the beginning row/column of the square
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
int main()
{
int puzzle[9][9];
string input;
for (int i=1; i <10; i++)
{
for (int j=1;j <10; j++)
{
cout << "Please insert the number for ["<< i << "," << j << "] (0 for no number)" << endl;
getline(cin, input);
int value = atoi(input.c_str());
puzzle[i-1][j-1] = value;
//get puzzle into correct format
}
}
if (solve(puzzle) == true)
{
string s;
cout << "Solving the puzzle..." << endl;
//print the puzzle to the screen
for (int i = 0; i<9;i++)
{
for (int j = 0; j<9; j++)
{
cout << puzzle[i][j] << ",";
}
cout << endl;
}
cout << "Press any button to escape";
getline(cin, s);
}
else
{
cout << "Can not solve the puzzle" << endl;
}
return 0;
}
Not sure why you need the code but here it is. Everything works properly, it just doesnt take input in the correct format currently.
As your numbers are only of 1 digit, you can:
int puzzle[9][9] = {};
for (int i = 1; i < 10; ++i)
{
cout << "Please input row #" << i << ": ";
getline(cin, input);
int j = 0;
const char *ptr = input.c_str();
while (*ptr)
{
if (isspace(*ptr)) ; // do nothing
else if (*ptr == ',') ++j; // new column
else puzzle[i - 1][j] = *ptr - '0';
++ptr;
}
}
To parse empty spaces as zerors, you need:
Initialize your matrix to zeros int puzzle[9][9] = { };
read the input line by line (each line representing a whole row)
use function strtok() to split (separate) the values using delimeter `','
for each separated value, trim it (i.e. remove spaces). Then, Use function atoi to covert it as an integer
Notice that you should check for empty separated string if (strlen(str))
I saw Conway's Game of Life and decided to make my own.
I have a bool array to represent the world, but the edges (Top and bottom) are acting weird, random cells becomes live.
In this code, it does not print the bottom and top of the world, but this is a bad solution.
The world "wraps" at the right and the left, causing even more problems, but that is for another time.
#include <iostream>
const int height = 20;
const int width = 20;
bool now_world[height][width];
bool then_world[height][width];
void clear_world();
void place_random_live_cells();
void then_world_initialization();
void print_world();
void generation_pass();
void update_worlds();
int main(int argc, const char * argv[])
{
using namespace std;
srand((unsigned)time(NULL));
int timer = 0;
int generation = 0;
clear_world();
place_random_live_cells();
then_world_initialization();
bool running = true;
while (running) {
if (timer == 50000000) {
cout << "Generation #" << generation << endl;
print_world();
generation_pass();
update_worlds();
++generation;
timer = 0;
}
++timer;
}//While (running) ends here
return 0;
}
void place_random_live_cells()
{
int percent = 30;
int max_live_cells = ((height * width) / 100) * percent;
int current_live_cells = 0;
while (current_live_cells < max_live_cells) {
int ycoords = 0 + (rand() % (height + 1));
int xcoords = 0 + (rand() % (width + 1));
if (now_world[ycoords][xcoords] == false) {
now_world[ycoords][xcoords] = true;
} else {
current_live_cells--;
}
++current_live_cells;
}
}
//A generation pass and cells die and some cells come to life
void generation_pass()
{
using namespace std;
int neighbours = 0;
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii+1][jjj ] == true) {
++neighbours;
}
if (now_world[iii+1][jjj-1] == true) {
++neighbours;
}
if (now_world[iii ][jjj+1] == true) {
++neighbours;
}
if (now_world[iii ][jjj-1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj ] == true) {
++neighbours;
}
if (now_world[iii-1][jjj-1] == true) {
++neighbours;
}
//Apply rules to the cells
//Dead cells with three live neighbours becomes alive
if (then_world[iii][jjj] == false && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with fewer than two, they die
if (then_world[iii][jjj] == true && neighbours < 2) {
then_world[iii][jjj] = false;
}
//Alive with 2 or three live neighbours live on unchanged
if (then_world[iii][jjj] == true && neighbours == 2) {
then_world[iii][jjj] = true;
}
if (then_world[iii][jjj] == true && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with more than three, they die
if (then_world[iii][jjj] == true && neighbours > 3) {
then_world[iii][jjj] = false;
}
//Dead cells without exactly three live neighbours remain dead
//Reset neighbour value to zero
neighbours = false;
}
}
}
//Make next generation identical to current
//This is only called once
void then_world_initialization()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
then_world[iii][jjj] = now_world[iii][jjj];
}
}
}
//Make the next generation be today
//This is called every generation
void update_worlds()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = then_world[iii][jjj];
}
}
}
//Set all cells to dead
void clear_world()
{
for (long iii = 0; iii < height; iii++) {
for (long jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = false;
then_world[iii][jjj] = false;
}
}
}
//Print world
void print_world()
{
using namespace std;
char live = 'X';
char dead = '.';
for (long iii = height; iii > 0; iii--) {
for (long jjj = width; jjj > 0; jjj--) {
if (iii != 0 && iii != height) {
if (now_world[iii][jjj]) {
cout << live;
} else {
cout << dead;
}
cout << " ";
}
}
cout << endl;
}
cout << endl;
}
Having done this for a course I taught in the past, the most common issue I always see people having is going outside the bounds of the array they're using.
If you look at the if statements in your nested for loop, I think you'll find some issues. For instance, in this case, what happens when iii equals (height-1) or jjj equals (width-1)?
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
You're going outside the bounds of your array and so your results will be undefined. You may get segfaults, but you may just also get spurious data. C++ doesn't enforce you staying within the bounds of the array you define.
Make sure you also handle cases like this:
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
What if iii equals zero?
Hope that helps.
You're trying to access out-of-boundary indexes in your array.
I'm not sure what behaviour you expect, but an easy way is to not calculate updates for cells on the edges.
So in generation_pass the loops should go from 1 till height-1.
I am making a Tic Tac Toe game and i created a function that inserts X or O into my array. I have run into one problem with my design. I call the function to make a move for X, but when it is the next players turn how do i make it call for O?
Is there a way after i put makeMove() i can just call somehow it to take in O turn instead of X. Because as you can see if i do X it will just always ask for X and not O. How can i make it choose to pull in X or O turn.
The problem is i need to only have one function that makes moves.
int main()
{
while(SOME CONDITION HERE)
{
printBoard();
cout << "Player X please choose a position: ";
makeMove('X');
cout << "Player O please choose a position: ";
makeMove('O');
}
}
int makeMove(char marker)
{
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = marker;
}
Start with this:
int main()
{
while(SOME CONDITION HERE)
{
printBoard();
cout << "Player X please choose a position: ";
makeMove('X');
cout << "Player O please choose a position: ";
makeMove('O');
}
}
int makeMove(char marker)
{
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = marker;
}
Note that you're going to want to change the SOME CONDITION HERE part, but you could quickly replace it by 1 and get the same behavior of your current script (actually, a bit better).
But you'll eventually want to put something there that makes sense -- something that will tell the program to stop prompting the players for positions and, say, declare a winner.
The following is just a more streamlined way of doing the same thing:
int main()
{
while(SOME CONDITION HERE)
{
printBoard();
makeMove('X');
makeMove('O');
}
}
int makeMove(char marker)
{
cout << "Player " << marker << " please choose a position: ";
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = marker;
return 0;
}
Note the added return 0 -- if you don't want to return something, you should just make makeMove return void so as not to be confusing.
You might try using an argument:
int makeMove(char player);
makeMove('O');
makeMove('X');
First of all, don't call main() recursively. Use a loop instead.
Secondly, use a variable (such as player below) to indicate whose turn it is.
int main()
{
char player = 'X';
while (/* game not finished */) {
printBoard();
makeMove(player);
player = (player == 'X') ? 'O' : 'X';
}
}
void makeMove(char player)
{
cout << "Player " << player << " please choose a position: ";
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = player;
}
Something like this may work... just be sure to use a loop for the moves.
char player = 'X';
while(...) {
cout << "choose position...";
makeMove(player);
if(player == 'X')
player = 'O';
else
player = 'X';
...
}
//in make move:
int makeMove(char player) {
int choosePosition = 0;
cin >> choosePosition;
ticTacBoard[choosePosition - 1] = player;
}
http://scripts.franciscocharrua.com/javascript/tic-tac-toe/
I added this to my website a few months ago. I admit it may be a bit complex, and in JavaScript, but it may be of some help.
JS:
function tic_tac_toe(blank_token, player_tokens, artificial_intelligence)
{
this.board = [[blank_token, blank_token, blank_token],
[blank_token, blank_token, blank_token],
[blank_token, blank_token, blank_token]];
this.blank_token = blank_token;
this.player_tokens = player_tokens;
this.display_choice = function() {};
this.declare_human_win = function() {};
this.declare_computer_win = function() {};
this.declare_tie = function() {};
this.artificial_intelligence = artificial_intelligence;
this.start =
function()
{
//Randomly choose a token for the human player.
var human_token_index = Math.floor(Math.random() * this.player_tokens.length);
this.human_player = this.player_tokens[human_token_index];
//Place the chosen token at the end of the array.
this.player_tokens[human_token_index] = this.player_tokens[this.player_tokens.length - 1];
this.player_tokens[this.player_tokens.length - 1] = this.human_player;
//Randomly choose a different token for the computer player.
var computer_token_index = Math.floor(Math.random() * (this.player_tokens.length - 1));
this.computer_player = this.player_tokens[computer_token_index];
//Clear the board.
for(var row = 0; row < 3; row++)
for(var collumn = 0; collumn < 3; collumn++)
{
this.place(this.blank_token, row, collumn);
}
if(Math.random() < 0.5)
{
this.turn = this.computer_player;
this.computer_turn();
}
else
{
this.turn = this.human_player;
}
};
//Returns the token of the winning player.
//If no one has won yet or the game is tied, returns the blank token.
//Used in combination with blank_token_count() to determine if the game is tied.
this.winner =
function()
{
var winner = this.blank_token;
//Check for 3 consecutive horisontal tokens.
for(var row = 0; row < 3; row++)
{
winner = this.board[row][0];
for(var collumn = 1; collumn < 3; collumn++)
{
if(this.board[row][collumn] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
}
//Check for 3 consecutive vertical tokens.
for(var collumn = 0; collumn < 3; collumn++)
{
winner = this.board[0][collumn];
for(var row = 1; row < 3; row++)
{
if(this.board[row][collumn] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
}
//Check for 3 consecutive diagonal tokens.
winner = this.board[0][0];
for(var row = 1; row < 3; row++)
{
if(this.board[row][row] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
winner = this.board[0][2];
for(var row = 1; row < 3; row++)
{
if(this.board[row][2 - row] != winner)
{
winner = this.blank_token;
}
}
if(winner != this.blank_token)
{
return(winner);
}
return(winner);
};
this.blank_token_count =
function()
{
var blank_token_count = 0;
for(var row = 0; row < 3; row++)
for(var collumn = 0; collumn < 3; collumn++)
{
if(this.board[row][collumn] == this.blank_token)
{
blank_token_count++;
}
}
return(blank_token_count);
};
this.computer_turn =
function()
{
//Lets the computer take its turn if the game is not over.
if(this.turn != this.blank_token)
{
this.turn = this.computer_player;
var computer_move = this.artificial_intelligence();
this.place(this.computer_player, computer_move.row, computer_move.collumn);
}
};
this.human_turn =
function(row, collumn)
{
this.place(this.human_player, row, collumn);
this.computer_turn();
}
this.place =
function(token, row, collumn)
{
if(row < 3 && collumn < 3 &&
((this.turn == token && this.board[row][collumn] == this.blank_token) || token == this.blank_token))
{
this.board[row][collumn] = token;
this.display_choice(token, row, collumn)
//Finishes the game in case a of a win or a tie.
//When the board is not being reset.
if(token != this.blank_token)
{
var winner_token = this.winner();
if(winner_token == this.human_player)
{
this.declare_human_win();
this.turn = this.blank_token;
}
if(winner_token == this.computer_player)
{
this.declare_computer_win();
this.turn = this.blank_token;
}
if(winner_token == this.blank_token && this.blank_token_count() == 0)
{
this.declare_tie();
this.turn = this.blank_token;
}
//Gives the human player a turn, if the game is not over.
if(this.turn == this.computer_player)
{
this.turn = this.human_player
}
}
}
};
}