Connect 4 building methods suggestions?

Started by
11 comments, last by alvaro 9 years, 6 months ago

I've been trying to build this game with a friend and so far he hasn't been much help so I am going to ask this community for suggestions and advice for building my Connect4 console game. So far I am filling the guts, I haven't put a method to check for 4 in a row yet and for both of the user's inputs. Also I don't know how to make my Move method start so you cant start dropping in the pieces.

I left a few notes in my comments on whether I should implement another class to store my row0,1,2,3,4,5,6 to see if my column is full or not.

I just want a more efficient ideas to create my code. I keep wanting to add more arguments in it!

If I should create another class could someone guide me on how I should do that with what I got, I'm not very familiar with gets, sets, values but it seems like I might need to use this?

I apologize if there's too much code here.

Much appreciated,

-Dustin


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Connect4
{
    class Program
    {

        static void Main(string[] args)
        {
            DisplayInstructions();
            Play();
        }
        public static void Play()
        {
            char[,] board = new char[6, 7]; //Create board.
            int rows = 5; //I dont know if I need these
            int columns = 6; //and this
            bool checkForFull = false; //Initialize method objects.
            int rowCheck = 0;
            Board(board, rows, columns); //Fills board with +'s.
            PrintBoard(board, rows, columns, checkForFull, rowCheck); //Display's board

            //char playerX = 'X';
            //char playerO = 'O';

            Move(board, rows, columns, checkForFull, rowCheck); //Start to play.

            Console.ReadKey();

        }
        //Checks input for validation might need better way to check the input.
        public static int PlayerTurn()
        {
            string inColumnNum;
            int columnPicked;
            inColumnNum = Console.ReadLine();
            columnPicked = int.Parse(inColumnNum);

            if (columnPicked >= 6 || columnPicked <= 1)
            {
                Console.WriteLine("Please pick the appropriate column");
                //Move(playerX, playerO);
            }

            return columnPicked;
        }
        //Checks for full board if so then declares as true.
        public static void FullBoard(char[,] board, int rows, int columns, bool checkForFull, int rowCheck)
        {
            int total = 0;
            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 7; j++)
                {
                    if (board[i, j] == 'X' || board[i, j] == 'O')
                    {
                        total += 1;
                        if (total == 42)
                        {
                            checkForFull = true;
                            PrintBoard(board, rows, columns, checkForFull, rowCheck);
                            Console.WriteLine("\nIt's a tie!");
                            PromptToPlayAgain();
                        }
                    }
                }
            }
            checkForFull = false;
        }

        public static void ColumnDepthKeeper(int rowCheck)
        {
            if (rowCheck == 0)
            {
                //Probably going to need another method to keep track of column depth
            }

        }

        public static char[,] Move(char[,] board, int rows, int columns, bool checkForFull, int rowCheck)
        {
            int row0 = 6;
            int row1 = 6;
            int row2 = 6;//Might have to go into another class to be stored becasue it will keep reseting if its placed here and cant be initialized outside the static class
            int row3 = 6;//Unless you want 7 methods or if you know a more effecient way of doing it?
            int row4 = 6;
            int row5 = 6;
            int row6 = 6;

            PlayerTurn();//I dont know how to start the game?

            while (checkForFull == false)
            {
                if (PlayerTurn() == 0) //Checks if player chooses column 1.
                {
                    if (row0 == 0) //Checks if column 1 is full.
                    {
                        Console.WriteLine("This column is full please choose an empty slot.");
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                    else //If not, adds new peice.
                    {
                        board[row0, PlayerTurn()] = 'X'; //Sets picked column and bottom of row with X or O.
                        row0--; //Update the row stored... This needs to come from another classs somehow?
                        row0 = rowCheck; //Sends to method to check if full
                        ColumnDepthKeeper(rowCheck);
                        PrintBoard(board, rows, columns, checkForFull, rowCheck); //Show the board again.
                        return Move(board, rows, columns, checkForFull, rowCheck); //Run through new input.
                    }
                }
                else if (PlayerTurn() == 1)
                {
                    if (row1 == 0)
                    {
                        Console.WriteLine("This column is full please choose an empty slot.");
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                    else
                    {
                        board[row1, PlayerTurn()] = 'X';
                        row1--;
                        row1 = rowCheck;
                        ColumnDepthKeeper(rowCheck);
                        PrintBoard(board, rows, columns, checkForFull, rowCheck);
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                }
                else if (PlayerTurn() == 2)
                {
                    if (row2 == 0)
                    {
                        Console.WriteLine("This column is full please choose an empty slot.");
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                    else
                    {
                        board[row2, PlayerTurn()] = 'X';
                        row2--;
                        row2 = rowCheck;
                        ColumnDepthKeeper(rowCheck);
                        PrintBoard(board, rows, columns, checkForFull, rowCheck);
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                }
                else if (PlayerTurn() == 3)
                {
                    if (row3 == 0)
                    {
                        Console.WriteLine("This column is full please choose an empty slot.");
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                    else
                    {
                        board[row3, PlayerTurn()] = 'X';
                        row3--;
                        row3 = rowCheck;
                        ColumnDepthKeeper(rowCheck);
                        PrintBoard(board, rows, columns, checkForFull, rowCheck);
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                }
                else if (PlayerTurn() == 4)
                {
                    if (row4 == 0)
                    {
                        Console.WriteLine("This column is full please choose an empty slot.");
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                    else
                    {
                        board[row4, PlayerTurn()] = 'X';
                        row4--;
                        row4 = rowCheck;
                        ColumnDepthKeeper(rowCheck);
                        PrintBoard(board, rows, columns, checkForFull, rowCheck);
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                }
                else if (PlayerTurn() == 5)
                {
                    if (row5 == 0)
                    {
                        Console.WriteLine("This column is full please choose an empty slot.");
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                    else
                    {
                        board[row4, PlayerTurn()] = 'X';
                        row5--;
                        row5 = rowCheck;
                        ColumnDepthKeeper(rowCheck);
                        PrintBoard(board, rows, columns, checkForFull, rowCheck);
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                }
                else if (PlayerTurn() == 6)
                {
                    if (row6 == 0)
                    {
                        Console.WriteLine("This column is full please choose an empty slot.");
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                    else
                    {
                        board[row6, PlayerTurn()] = 'X';
                        row6--;
                        row6 = rowCheck;
                        ColumnDepthKeeper(rowCheck);
                        PrintBoard(board, rows, columns, checkForFull, rowCheck);
                        return Move(board, rows, columns, checkForFull, rowCheck);
                    }
                }
                return Move(board, rows, columns, checkForFull, rowCheck);

            }
            Console.WriteLine("Game Over.");
            PromptToPlayAgain(); //When the board is full and check for full = true then ask to play again.
            return Move(board, rows, columns, checkForFull, rowCheck); //Need this just cause.
        }
        //Fills the empty array.
        public static void Board(char[,] board, int rows, int columns)
        {
            for (int i = 0; i < 6; i++)
            {
                for (int z = 0; z < 7; z++)
                {
                    board[i, z] = '+';
                }
            }
        }
        //Will print the board when called.
        public static void PrintBoard(char[,] board, int rows, int columns, bool checkForFull, int rowCheck)
        {
            {
                Console.WriteLine("Current Board (user1 = O, user2 = X): \n");
                for (int i = 0; i < 6; i++)
                {
                    for (int j = 0; j < 7; j++)
                    {
                        Console.Write(board[i, j]);
                    }
                    Console.WriteLine();
                }
            }
        }
        //Will ask if your done player when called.
        public static void PromptToPlayAgain()
        {

            DialogResult Result = MessageBox.Show("Lets play again!",
                "Message", MessageBoxButtons.YesNo,
                MessageBoxIcon.Exclamation);
            if (Result == DialogResult.Yes)
            {
                Play();
            }
            else
            {
                EndGame();
            }
        }
        //Ends the game.
        public static void EndGame()
        {
            Console.WriteLine("You chose to end the game.\nThis game is going to close in 4 seconds...");
            System.Threading.Thread.Sleep(4000);
            System.Environment.Exit(0);
        }
        //Displays the instructions once.
        public static void DisplayInstructions()
        {
            Console.WriteLine("I'm glad you've chosen to play Connect 4!\nTo play enter the row player X or player O wants to put his/hers piece.");
        }
    }
}

Advertisement
Very repetitive code is a bad sign.

            int row0 = 6;
            int row1 = 6;
            int row2 = 6;//Might have to go into another class to be stored becasue it will keep reseting if its placed here and cant be initialized outside the static class
            int row3 = 6;//Unless you want 7 methods or if you know a more effecient way of doing it?
            int row4 = 6;
            int row5 = 6;
            int row6 = 6;


Have you heard of arrays?

You need to come up with a board representation. Make a class `Board' that provides methods to make a move, to generate a list of available moves, to determine if the game is over... If you have any repetitive code, you are doing it wrong.

Okay thanks for your reply but what you said is what I already figured. I need help setting up my new class 'Board' methods if that's the case. So I create my array in a method in my 'Board' class and then what methods do I fill it with like I said, I haven't worked with more than one class very much in my classes. Here's what I'm starting with...


    class Board
    {
        public Board()
        {

        }

        public void BoardArray()
        {
            char[,] board = new char[6, 7];
        }

        public void AvailableMoves()
        {

        }

        public void MakeMove()
        {

        }
    }
The data needs to be held by your class, not inside a method.

Can you describe in English what data you think you will need to represent the board? I'll help you from there.

Not super clear what you want, but I can give general suggestions.

First, use an array as Alvaro said.

Each spot in the array will have one of three values (empty, black, and red).

Place the pieces with the numbers to start (although I'd switch over to arrow control later).

When you press one, just check the top position in the array, if it's not empty, don't do anything- keep waiting for input (or give them an error message) and don't change to the next person's turn. If it's empty, then check the next one down. If the next one down is full, with black or red, then it will go in the first one. If the next one is empty, then check the next one. Keep checking until one is full, and place your piece on the location above it, or you reach the bottom (in which case, place it at the bottom). Then change to the next person's turn.

About checking (when you get to it):

When a new piece is added (and only at that time), check the surrounding pieces in each direction, stepping out and adding to your count (for that angle) if and only if it's of the same type, up to the edge of the board.

You do this by reading the value you have in the location of the array.

Piece added. Check right. Is it the same kind of piece as the one just added? If yes, +1 Horizontal, step another right and repeat. If no, reset to original position and move on to next direction (maybe left).

You need to do this for:

right and left (both add to Horizontal)

down (adds to vertical)

upRight (going up and to the right), and downLeft, both add to slash (/ or another name if you want, that's just easy)

upLeft and downRight, both add to backSlash (\ or something else)

I would suggest you keep counting, even if one is four or more than four. You can add on bonus point or something for multiples, or rows of more than four.

My Board is going to need to know...

-The size of the array

-What index's are empty

-When a column is full

-When the board is full

-When is there 4 in a row

-Whose turn it is

-Is there a tie

-Who is the winner

That's all I can think of that my board class should keep track of Alvero?

And thanks StarMire for your input. I'm going to give your thoughts a go tomorrow, I need a fresh start working on this. I don't know why I've been using X's and O's hah.

Your board needs to know only 3 things - is the cell empty/black or red.

Just do an array of ints, for example 0 will be empty, 1 would be black and 2 red.

You can write functions for the other cases you mentioned. These functions should be called per update of the board.

(whose turn it is and who is the winner can be saved in state variables)

Example:


//is the board full - this is just an example - it can be severely optimized
//by just adding a counter that starts with the number of the board cells and diminishes
//every time you put a new piece
bool isFull()
{
    //let int arr[BOARD_WIDTH][BOARD_HEIGHT] be the array for the board then:
    for( int i=0; i<BOARD_WIDTH; i++ )
    {
        for( int j=0; j<BOARD_HEIGHT; j++ )
        {
            if(arr[i][j] == 0 )
                return false;
        }
    }
    return true;
}

Here's an example of the check you can do when adding a piece:


//x and y are the coordinates of the new piece added
int countPieces( int x, int y, int color, int dx, int dy, int number = 4 )
{
    int counter = 0;
    for( int i = 0; i < number; i++ )
    {
        if( 0 > x + i*dx && x + i*dx >= BOARD_WIDTH && 0 > y + i*dy && y + i*dy >= BOARD_HEIGHT )
        {
            return counter;
        }
        else
        {
            if( arr[x+i*dx][y+i*dy] == color )
            {
                counter++;
            }
            else
            {
               return counter;
            }
        }
    }
    return counter;
}

You can put dx = 1 for checking right, dx = -1 for checking left etc.

Btw never mind, my countPieces method fails in some specific cases - do not use it.

Okay I'm pleased to note with some of your guy's help I got everything working except for checking for 4 in a row.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Connect4
{
    class Program
    {
        static int row0 = 6, row1 = 6, row2 = 6, row3 = 6, row4 = 6, row5 = 6, row6 = 6;
        static int checker;
        static void Main(string[] args)
        {
            DisplayInstructions();
            Play();
        }
        public static void Play()
        {
            char[,] board = new char[6, 7]; //Create board.
            int rows = 5; //I dont know if I need these
            int columns = 6; //and this
            checker = 0;
            int rowCheck = 0;    
            
            Board(board, rows, columns); //Fills board with +'s.
            PrintBoard(board, rows, columns, rowCheck); //Display's board
            
            PutPiece(board, rows, columns, rowCheck); //Start to play.
            Console.ReadKey();
        }
        //Checks input for validation might need better way to check the input.
        public static int ColumnInput()
        {
            string inColumnNum;
            int columnPicked;
            inColumnNum = Console.ReadLine();        
            while (int.TryParse(inColumnNum, out columnPicked) == false)
            {
                Console.WriteLine("Invalid input");
                Console.Write("Please re-enter an column between 0 and 6. \n");
                inColumnNum = Console.ReadLine();            
            }
            if ((columnPicked < 0) || (columnPicked > 6))
            {
                Console.WriteLine("Please pick the appropriate column");
            }
            
            return columnPicked;          
        }
        public static int PlayerTurn(int Player)
        {
            if (Player == 0)
            {
                return Player;
            }
            else if (Player == 1)
            {
                return Player;
            }
            return Player;
        }
        //Checks for full board if so then declares as true.
        public static Boolean FullBoard()
        {
            bool fullCheck = false;            
            Console.WriteLine(checker);
            if (checker == 42)
            {
                fullCheck = true;
            }

            return fullCheck;
        }

        public static int Win(char[,] board, int x, int y)
        {    
            //Algorythm?
        }

        public static void PutPiece(char[,] board, int rows, int columns, int rowCheck)
        {
            
            while (FullBoard() != true)
            {
                if (PlayerTurn(0) == 0)
                {
                    Console.WriteLine("Player 1 turn.");
                    int column = ColumnInput();
                    if (column == 0)
                    {
                        int num = UpdateCol1(row0);
                        board[num, column] = 'X';
                    }
                    if (column == 1)
                    {
                        int num = UpdateCol2(row1);
                        board[num, column] = 'X';
                    }
                    if (column == 2)
                    {
                        int num = UpdateCol3(row2);
                        board[num, column] = 'X';
                    }
                    if (column == 3)
                    {
                        int num = UpdateCol4(row3);
                        board[num, column] = 'X';
                    }
                    if (column == 4)
                    {
                        int num = UpdateCol5(row4);
                        board[num, column] = 'X';
                    }
                    if (column == 5)
                    {
                        int num = UpdateCol6(row5);
                        board[num, column] = 'X';
                    }
                    if (column == 6)
                    {
                        int num = UpdateCol7(row6);
                        board[num, column] = 'X';
                    }
                    Win(board, rows, columns);
                    PrintBoard(board, rows, columns, rowCheck);
                    PlayerTurn(1);
                }
                if (PlayerTurn(1) == 1)
                {
                    
                    Console.WriteLine("Player 2 turn.");
                    int column = ColumnInput();
                    if (column == 0)
                    {
                        int num = UpdateCol1(row0);
                        board[num, column] = 'O';
                    }
                    if (column == 1)
                    {
                        int num = UpdateCol2(row1);
                        board[num, column] = 'O';
                    }
                    if (column == 2)
                    {
                        int num = UpdateCol3(row2);
                        board[num, column] = 'O';
                    }
                    if (column == 3)
                    {
                        int num = UpdateCol4(row3);
                        board[num, column] = 'O';
                    }
                    if (column == 4)
                    {
                        int num = UpdateCol5(row4);
                        board[num, column] = 'O';
                    }
                    if (column == 5)
                    {
                        int num = UpdateCol6(row5);
                        board[num, column] = 'O';
                    }
                    if (column == 6)
                    {
                        int num = UpdateCol7(row6);
                        board[num, column] = 'O';
                    }    
                    PrintBoard(board, rows, columns, rowCheck);
                    Win(board, rows, columns);
                    PlayerTurn(0);
                }
            }
            PromptToPlayAgain();
        }

        public static int UpdateCol1(int rowNum)
        {
            if (row0 != 0)
            {
                checker++;
                row0--;
            }
            else
            {
                Console.WriteLine("This column is full, choose another.");
                ColumnInput();
            }                            
            return row0;
        }
        public static int UpdateCol2(int rowNum)
        {
            if (row1 != 0)
            {
                checker++;
                row1--;
            }
            else
            {
                Console.WriteLine("This column is full, choose another.");
                ColumnInput();
            }
            return row1;
        }
        public static int UpdateCol3(int rowNum)
        {
            if (row2 != 0)
            {
                checker++;
                row2--;
            }
            else
            {
                Console.WriteLine("This column is full, choose another.");
                ColumnInput();
            }
            return row2;
        }
        public static int UpdateCol4(int rowNum)
        {
            if (row3 != 0)
            {
                checker++;
                row3--;
            }
            else
            {
                Console.WriteLine("This column is full, choose another.");
                ColumnInput();
            }
            return row3;
        }
        public static int UpdateCol5(int rowNum)
        {
            if (row4 != 0)
            {
                checker++;
                row4--;
            }
            else
            {
                Console.WriteLine("This column is full, choose another.");
                ColumnInput();
            }
            return row4;
        }
        public static int UpdateCol6(int rowNum)
        {
            if (row5 != 0)
            {
                checker++;
                row5--;
            }
            else
            {
                Console.WriteLine("This column is full, choose another.");
                ColumnInput();
            }
            return row5;
        }
        public static int UpdateCol7(int rowNum)
        {
            if (row6 != 0)
            {
                checker++;
                row6--;
            }
            else
            {
                Console.WriteLine("This column is full, choose another.");
                ColumnInput();
            }
            return row6;
        }
        //Fills the empty array.
        public static void Board(char[,] board, int rows, int columns)
        {
            for (int i = 0; i < 6; i++)
            {
                for (int z = 0; z < 7; z++)
                {
                    board[i, z] = '+';
                }
            }
        }
        //Will print the board when called.
        public static void PrintBoard(char[,] board, int rows, int columns, int rowCheck)
        {
                Console.WriteLine("Current Board, Player 1 = X, Player 2 = O. \n");
                for (int i = 0; i < 6; i++)
                {
                    for (int j = 0; j < 7; j++)
                    {
                        
                        Console.Write(board[i, j]);
                    }
                    Console.WriteLine();
                }
        }
        //Will ask if your done player when called.
        public static void PromptToPlayAgain()
        {
            DialogResult Result = MessageBox.Show("Lets play again!",
                "Message", MessageBoxButtons.YesNo,
                MessageBoxIcon.Exclamation);
            if (Result == DialogResult.Yes)
            {
                Play();
            }
            else
            {
                EndGame();
            }
        }
        //Ends the game.
        public static void EndGame()
        {
            Console.WriteLine("You chose to end the game.\nThis game is going to close in 4 seconds...");
            System.Threading.Thread.Sleep(4000);
            System.Environment.Exit(0);
        }
        //Displays the instructions once.
        public static void DisplayInstructions()
        {
            Console.WriteLine("I'm glad you've chosen to play Connect 4 with X's and O's!\nTo play enter the row player X or player O wants to put his/hers piece.");
        }
    }
}


static int row0 = 6, row1 = 6, row2 = 6, row3 = 6, row4 = 6, row5 = 6, row6 = 6;

I won't continue reading that code. Use a freaking array!!

Come on! I busted my balls to make this functional! Please just give me advice on how to create an algorithm for four in a row, I am soooo close. Besides this is my first year coding.

This topic is closed to new replies.

Advertisement