Jump to content
  • Advertisement
Sign in to follow this  
guzumba

C# Connect Four game help

This topic is 3628 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone, Im trying to write a program for a connect four game. This code doesnt print the _'s of my board and im not sure why. It also print my moves side ways when im wanting it to print upwards like a regular connect four game.
using System;

public class Proj6
{
    public static string[,] board = new string[6, 7];
    public static int[] columns = new int[7];

    public static void Main()
    {
        bool game = true;
        Proj6.columnCount();

        while (game)
        {
            Proj6.move1();
            Proj6.move2();
        }
    }

    public static int Row(int n)
    {
        int m = n;
        columns[m] -= 1;
        return columns[m];
    }

    public static void columnCount()
    {
        for (int i = 0; i < columns.Length - 1; i++)
        {
            columns = 5;
        }

    }

    public static void move1()
    {
        Proj6.printBoard();
        Console.Write("\nUser 1 (O), enter a column (0-6): ");
        int move = Convert.ToInt32(Console.ReadLine());
        int row = Proj6.Row(move);

        board[move, row] = "O";
    }

    public static void move2()
    {
        Proj6.printBoard();
        Console.Write("\nUser 2 (X), enter a column (0-6): ");
        int move = Convert.ToInt32(Console.ReadLine());
        int row = Proj6.Row(move);

        board[move, row] = "X";
    }

    public static void Board()
    {
        bool buildBoard = true;
        while (buildBoard)
        {
            for (int i = 0; i < 6; i++)
            {
                for (int j = 0; j < 7; j++)
                {
                    board[i, j] = "_ ";
                }
            }
            buildBoard = false;
        }
    }    
    public static void printBoard()
    {
        {
            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]);
                    if (j == 6)
                    {
                        Console.WriteLine();
                    }
                }
            }
        }
    }
}


Thanks everyone for your help

Share this post


Link to post
Share on other sites
Advertisement
It looks like your Board function (the one that initializes your board with '_') is never called.

As far as your moves, the problem lies in a couple of places. Carefully inspect your Row function. Keep in mind what you initialize the column array to, and what happens when a piece is placed in a column. Actually step through the code with a pencil and paper and see what happens. Compare that to what you expect to happen. It's a small mistake that you won't catch unless you actually follow your own code and see it yourself.

Also take a closer look at this line in your move functions.

board[move, row] = "O";


Are you sure you're indexing board the right way? Did you intend for it to be indexed by [row, column] or by [column, row]. Hint: There are only two ways to index it and your program is misbehaving, so it must be the other way!

Share this post


Link to post
Share on other sites
Quote:
Original post by guzumba
This code doesnt print the _'s of my board and im not sure why.


You never actually call the Board() function.

Quote:
It also print my moves side ways when im wanting it to print upwards like a regular connect four game.


Look carefully at the code that actually puts the moves into the grid. Which index represents rows and which represents columns? Should the user be specifying a row or a column? Therefore...




You're also doing a bunch of rather strange and/or useless things. Of note:

0)

public class Proj6
{


Clearly you don't intend to make objects of type Proj6 (BTW, what on earth kind of name is that?) but are just using it to store static functions. This is C#, not Java. You have namespaces; use them.

1)

public static void Main()
{
bool game = true;
Proj6.columnCount();


Repeated several times: You're already writing code within Proj6, so you don't need to say to look for a function within Proj6. That will be the first place the compiler looks.

2)

public static int Row(int n)
{
int m = n;
columns[m] -= 1;
return columns[m];
}


Why not just use n directly?

3)

public static void move1()
public static void move2()


Can you think of a way to use the same function for both tasks? What are the differences between the two functions? In programming, we constantly seek to find things that are almost the same, and handle them in one spot: that way, if we change our mind about the handling, we only have to change it in one place.

4)

public static void Board()
{
bool buildBoard = true;
while (buildBoard)
{
...
buildBoard = false;
}
}


Exactly what purpose do you think the outer while loop is serving?

Share this post


Link to post
Share on other sites
Thanks for the post everyone! I have fixed alot of the code and gotten alot farther. To answer your question about why im using "public class Proj6". I havent really learned about namespaces yet. Im sure its coming up in the book im reading. Im also typing "Proj6.Board();" instead of "Board();" because im getting used to calling class names. I was reading that you do this for calling classes from other files.

Here is the code I have updated. I am still needing help though. Im needing help checking for a winner. Ive tried a couple things but nothing is coming to mind. Im thinking I have to check the board array with a for loop, and have if statements within. But im confused how to get started. If anyone can help me get started that would be awesome. Thanks everyone!


using System;

public class Proj6
{
public static string[,] board = new string[6, 7];
public static int[] columns = new int[7];
public static bool playerX = true;
public static bool game = true;

public static void Main()
{
// controls the flow of the program by calling various methods
// and has while loop for repeating certain method calls

Proj6.columnCount();
Proj6.Board();

while (game)
{
Proj6.move();
Proj6.winner();
Proj6.boardFull();
}
}

public static int Row(int n)
{
// makes sure pieces are not replacing opponent
// players pieces by returning spot for piece to fall

columns[n] -= 1;
return columns[n];
}

public static void columnCount()
{
// tells program bottom of game board starts
// and where the pieces must fall in each column

for (int i = 0; i < columns.Length; i++)
{
columns = 6;
}
}

public static void move()
{
// ask user for column number and places an X or O
// on board at column number user selected

Proj6.printBoard();

if (playerX)
{
Console.Write("\nUser 1 (X), enter a column (0-6): ");
}
else
{
Console.Write("\nUser 1 (O), enter a column (0-6): ");
}

int move = Convert.ToInt32(Console.ReadLine());
int row = Proj6.Row(move);

if (playerX)
{
board[row, move] = "X ";
playerX = false;
}
else
{
board[row, move] = "O ";
playerX = true;
}

}

public static void Board()
{
// builds board array, blank board with _'s

for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 7; j++)
{
board[i, j] = "_ ";
}
}
}
public static void printBoard()
{
// prints updated board _'s replaced with
// X's and O's at users column choice

Console.WriteLine("Current Board (user1 = X, user2 = O): \n");
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 7; j++)
{
Console.Write(board[i, j]);
if (j == 6)
{
Console.WriteLine();
}
}
}
}

public static void boardFull()
{
// adds up X's and O's to see if board is full
// and if a tie has occurred

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)
{
Proj6.printBoard();
Console.WriteLine("\nIts a tie...");
game = false;
break;
}
}
}
}
}

public static void winner()
{
// checks if player 1 or 2 has connected four pieces
// either horizontal, vertical or diagonal

}
}

Share this post


Link to post
Share on other sites
Here's my implementation of your Connect4 game.


using System;

// we use namespaces to help organize our projects and keep name
// clashes from happening. This let's us use more descriptive
// names for our types without fear of having them conflict
// with a built-in type.
namespace Connect4
{
// instead of having two dimensional arrays, which are
// unwieldy, let's divide some of the work into another class
class Row
{
char[] pieces;

public char[] Pieces
{
get { return pieces; }
}

public Row(int columnCount, char emptyCharacter)
{
pieces = new char[columnCount];
for (int i = 0; i < columnCount; i++)
pieces = emptyCharacter;
}
}

// give your classes descriptive names. There's no
// need to abreviate anything; it really won't save
// you any time.
class Connect4Game
{
// these constants make changing the size of
// the board easy. You only have to do it in one place
const int RowCount = 6;
const int ColumnCount = 7;

// this is the entry point for the game
static void Main()
{
// define the characters that will represent each piece
char[] pieceCharacters = new char[3];
pieceCharacters[0] = '_';
pieceCharacters[1] = 'X';
pieceCharacters[2] = 'O';

// define the rows of the game board
Row[] rows = new Row[RowCount];
for (int i = 0; i < RowCount; i++)
rows = new Row(ColumnCount, pieceCharacters[0]);

// this will hold the player who is going
// to make his move next. we start with player 1,
// and alternate between him and player 2
int currentPlayer = 1;
int previousPlayer = 2;

// enter the main loop. we should loop
// until the user wants to exit
while (true)
{
// clear the screen each time we loop
Console.Clear();

// draw the board
DrawBoard(rows);

// check for a full board (tie)
if (CheckForTie(rows, pieceCharacters[0]))
{
// the game's over, and the result is a tie. break out of the loop
// to end the game
Console.WriteLine("It's a tie!");
break;
}
else if (CheckForWin(rows, pieceCharacters[previousPlayer]))
{
// the game's over, and one of the players won. since one of the players
// just made a move, he's the one that won the game
Console.WriteLine("Player " + previousPlayer + " (" + pieceCharacters[previousPlayer] + ") wins!");
break;
}

// prompt the user for a move
Console.Write("Player " + currentPlayer + " (" + pieceCharacters[currentPlayer] + "), ");
Console.Write("enter a column (1 - 7): ");

// read the input. if the user doesn't enter a valid answer, we will tell him so and
// then loop around to let him try again
string input = Console.ReadLine();
int choice = 0;
if (!int.TryParse(input, out choice) || choice < 1 || choice > 7 ||
!AddPiece(rows, choice - 1, pieceCharacters[currentPlayer]))
{
// tell the user that he screwed up
Console.WriteLine();
Console.WriteLine("Invalid input. Please try again.");
Console.WriteLine("-- Press any key to continue --");

// wait for confirmation before continuing
Console.ReadLine();
}
else
{
// otherwise, update the current player and wait for another turn
previousPlayer = currentPlayer;
if (currentPlayer == 1)
currentPlayer = 2;
else
currentPlayer = 1;
}
}

// the game's done now
Console.WriteLine("Thanks for playing!");
Console.WriteLine("-- Press any key to exit --");
Console.ReadLine();
}

// this function will draw the board for us
static void DrawBoard(Row[] rows)
{
// print each row
foreach (Row row in rows)
Console.WriteLine(row.Pieces);
Console.WriteLine();
}

// this function adds a piece to the board, figuring
// out the correct row it should go in
// if we can't add the piece (because the column is full),
// we will return false to indicate an error
static bool AddPiece(Row[] rows, int column, char character)
{
// work our way up from the bottom, with the last row
// in the array being the bottom of the board
for (int i = rows.Length - 1; i >= 0; i--)
{
// if this row is empty here, we can add the piece
if (rows.Pieces[column] == '_')
{
// once we add the piece, we don't need to loop anymore
rows.Pieces[column] = character;
return true;
}
}

// if we made it this far, the column is full
// return false to indicate an error
return false;
}

// this function checks for a full board, which indicates a tie
static bool CheckForTie(Row[] rows, char emptyPiece)
{
// check each piece to see if it contains a piece or is empty
foreach (Row row in rows)
foreach (char piece in row.Pieces)
if (piece == emptyPiece)
return false;

// if we get this far, it's a tie
return true;
}

// this function checks to see if there is a winner
static bool CheckForWin(Row[] rows, char playerCharacter)
{
// four in a row is a win
string playerString = new string(playerCharacter, 4);

// first check for a horizontal win (the easiest kind)
foreach (Row row in rows)
if (new string(row.Pieces).Contains(playerString))
return true;

// next check for a vertical win
string[] columns = new string[ColumnCount];
foreach (Row row in rows)
for (int i = 0; i < ColumnCount; i++)
columns += row.Pieces;

foreach (string column in columns)
if (column.Contains(playerString))
return true;

// finally, check for a diagonal win. this is the hardest kind
string[] diagonals = new string[ColumnCount + RowCount - 1];
for (int i = 0; i < ColumnCount + RowCount - 1; i++)
diagonals = "";

int offset = RowCount - 1;
foreach (Row row in rows)
{
for (int i = 0; i < ColumnCount; i++)
diagonals[offset + i] += row.Pieces;
offset--;
}

foreach (string diagonal in diagonals)
if (diagonal.Contains(playerString))
return true;

// otherwise, no win was found
return false;
}
}
}

Share this post


Link to post
Share on other sites
It keeps telling me not all code paths return a value. Can anyone tell me why please? The code looks fine to me.



public static int Row(int n)
{
// makes sure pieces are not replacing opponent
// players pieces by returning spot for piece to fall

columns[n] -= 1;
while (still2)
{
if (columns[n] < 0)
{
Console.WriteLine("Column is Full try another one");
Proj6.printBoard();
continue;
}
else
{
return columns[n];
}
}
}

Share this post


Link to post
Share on other sites
What is 'still2'? How can its value change? If it did change, and the loop wasn't exited, where would the code be? (Answer: at the end of the function, and there's no return value there.)

The problem is that you're trying to handle the "tell the user he's an idiot" logic in the same function that detects his idiocy. In programming this tends not to work very well. You need to communicate back to the calling code that the user's selected column is full, and handle the loop there. Pay careful attention to Mike.Popolowski's addPiece() function for an example of how code is normally structured to handle this sort of thing.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!