码迷,mamicode.com
首页 > 编程语言 > 详细

用C语言完成:三子棋。

时间:2017-10-22 22:08:27      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:inpu   computer   bre   棋盘   二维   ini   开始   ==   简单的   

今天要完成一个相对于之前学习更有挑战性的小程序——三子棋。

相信我们大部分人都接触过三子棋,这是一款操作简单易上手的小游戏。

技术分享

先简单介绍一下三子棋的规则,方便我们接下来的编程和理解。规则如下:

在九宫格棋盘上,只要将自己的三个棋子走成一条线(横、竖、对角线),对方就算输了。

 

规则很简单,但是我们应该从哪里入手完成这个三子棋程序呢?

 

首先,我们的游戏程序应该先有个菜单页面,这个菜单页面用来让用户操作选择玩游戏,或是退出。

界面可以很简单,只需要几条 printf 语句即可。

这里我们尽可能用函数来完成游戏的功能:

void menu()
{
    printf("***************************************\n");
    printf("*      1.play             0.exit      *\n");
    printf("***************************************\n");
}

这就是一个简单的主菜单界面,效果如下:

技术分享

既然菜单中有选项,我们就必须要设计一个变量用来接收用户的选择。

而且游戏程序本身应该允许用户反复进行玩耍,所以在主函数中,我们需要用一个循环来完成这个功能。

do-while循环在调用时会先运行循环体,而后在进行判断,所以这里我们选择使用do-while循环:

int main()
{
    int choice;
    do
    {
        menu();
        printf("Input your choice:");
        scanf("%d", &choice);
        switch (choice)
        {
        case 1:
            game();
            break;
        case 0:
            break;
        default:
            printf(" Input error!Please try again.\n");
            break;
        }
    } while (choice);
    return 0;
}

由于用户选择选项1时我们需要为用户启动游戏程序,所以这里我们使用一个switch语句来接受用户的选择。

选择0时退出程序,所以我们只需要跳出循环,即可退出。

而输入0、1之外的值时,我们应该向用户报输入错误,所以在default中输出一条报错信息。

接下来就是我们程序的重点——三子棋游戏本身了。

先创建一个game()函数,里面的内容我们一步步来填充。

void game()
{
}

在程序开始阶段,我们首先要创建一个3*3的二维字符数组,

由于长和宽我们要经常用到,为了后续修改方便,我们采用宏定义方式:

#define ROWS 3
#define COLS 3

接下来在game()函数中创建数组:

char board[ROWS][COLS];

并将这个数组进行初始化,因为这个数组在后续需要输出展示在用户面前,所以我们将值初始化为空格“ ”。

初始化用函数进行完成:

void init_board(char board[ROWS][COLS], int rows, int cols)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] =  ;
        }
    }
}

接下来,我们应该输出这个数组棋盘,来检查一下是否初始化完成,

但我们没有展示棋盘的函数,所以我们需要完成这个显示棋盘函数:

void show_board(char board[ROWS][COLS], int rows, int cols)
{
    int i;
    for (int i = 0; i < rows; i++)
    {
        printf("  %c | %c | %c  \n",board[i][0],board[i][1],board[i][2]);
        if (i != rows - 1)
            printf(" ---|---|--- \n");
    }    
}

这里需要利用循环来输出我们棋盘的格式,格式不统一,可以根据自己的喜好进行修改。

下面展示一下我这个代码所输出的棋盘:

技术分享

上面已经看出我的棋盘初始化已经完成,所以接下来我们需要考虑如何让电脑或用户进行下棋操作了。

电脑走需要让电脑产生随机坐标,然后在数组的这个坐标位置放入一个“X”作为电脑的棋子。

所以代码如下:

void ComputerMove(char board[ROWS][COLS], int rows, int cols)
{

    int x, y;
    printf("Compter‘s turn to move:\n");
    while (1)
    {
        x = rand() % rows;
        y = rand() % cols;
        if (board[x][y] ==  )
        {
            board[x][y] = X;
            break;
        }
    }
}

rand()是用来生成随机数的,这里我们还需要在主函数main中加上一行代码。

由于我们不希望他多次生成随机数,生成一次就足够用了,所以直接在创建choice变量的下一行加上下面这个代码即可:

srand((unsigned int)time(NULL));

注意生成随机数需要引用time.h这个头文件。

电脑下完棋后,需要轮到我们的用户进行下棋操作,这个函数和电脑下棋大同小异,

但是要注意人的习惯不会输入(0,0)这个坐标,而是输入(1,1)。

所以这里我们要给传过去的参数-1。

解决这个问题后的代码如下:

void player_move(char board[ROWS][COLS], int rows, int cols)
{
    int x, y;
    printf("Player‘s turn to move:\n");
    while (1)
    {
        printf("Input x and y(like x y):\n");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= rows && y >= 1 && y <= cols)
        {
            if (board[x - 1][y - 1] ==  )
            {
                board[x - 1][y - 1] = O;
                break;
            }
            else printf("The location has been taken!Please try again.\n");
        }
        else printf(" Input error!Please try again.\n");
    }
}

在双方走完后,我们需要判断是否胜利,也就是判断之前我们提到的规则,

这时我们需要编写一个checkwin()函数来检测并返回一个值表示谁获胜。

代码如下:

char check_win(char board[ROWS][COLS], int rows, int cols)
{
    int i;
    for (i = 0; i < rows; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] !=  )
            return board[i][1];
    }
    for (i = 0; i < cols; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] !=  )
            return board[1][i];
    }
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] !=  )
        return board[1][1];
    else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] !=  )
        return board[1][1];
    else if (is_full(board, rows, cols))
        return q;
    return 0;
}

由于可能出现棋盘下满,却没人获胜的情况,
所以我们需要在其中判断一下平局的情况,

这里我们编写了一个is_full()函数,用来判断棋盘是否下满:

static int is_full(char board[ROWS][COLS], int rows, int cols)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            if (board[i][j] ==  )
                return 0;
        }
    }
    return 1;
}

注意这个函数我们只在checkwin中会使用到,我们并不希望它在其他源文件的函数中被使用,所以我们加上了static。

这时程序的雏形已经基本完成,我们只需要按我们自己理解的游戏步骤来完成game()函数即可。

所以完成后的game()函数如下所示:

void game()
{
    char win = 0;
    char arr[ROWS][COLS];
    init_board(board, ROWS, COLS);
    do
    {
        computer_move(board, ROWS, COLS);
        show_board(board, ROWS, COLS);
        win = check_win(board, ROWS, COLS);
        if (win != 0)
            break;
        player_move(board, ROWS, COLS);
        show_board(board, ROWS, COLS);
        win = check_win(board, ROWS, COLS);
    } while (win == 0);
    if (win == X)
        printf("You lose!Good luck next time!\n");
    if (win == O)
        printf("You win!Congratulations!\n");
    if (win == q)
        printf("The score was tied!Good luck next time!\n");
}

这样,将上面各个部分合在一起,这个程序就被我们完成了。

 

下面放上我自己写的,比较丑陋的代码:

我的代码分为三部分,

第一部分是头文件:

#ifndef __CHESS_H__
#define __CHESS_H__

#include<stdio.h>
#include<time.h>
#include<Windows.h>

#define ROWS 3
#define COLS 3

void show_board(char board[ROWS][COLS], int rows, int cols);
void init_board(char board[ROWS][COLS], int rows, int cols);
void computer_move(char board[ROWS][COLS], int rows, int cols);
void player_move(char board[ROWS][COLS], int rows, int cols);
char check_win(char board[ROWS][COLS], int rows, int cols);

# endif//__CHESS_H__

第二部分是源文件的函数部分:

#include"3chess.h"

void show_board(char board[ROWS][COLS], int rows, int cols)
{
    int i;
    for (int i = 0; i < rows; i++)
    {
        printf("  %c | %c | %c  \n",board[i][0],board[i][1],board[i][2]);
        if (i != rows - 1)
            printf(" ---|---|--- \n");
    }    
}

void init_board(char board[ROWS][COLS], int rows, int cols)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            board[i][j] =  ;
        }
    }
}

void computer_move(char board[ROWS][COLS], int rows, int cols)
{
    int x, y, i;
    printf("Compter‘s turn to move:\n");
    while (1)
    {
        x = rand() % rows;
        y = rand() % cols;    
        for (i = 0; i < rows; i++)
        {
            if (board[i][0] == board[i][1] && board[i][0] == X && board[i][2] ==  )
            {
                board[i][2] = X;
                goto flag1;
            }
            else if (board[i][1] == board[i][2] && board[i][1] == X && board[i][0] ==  )
            {
                board[i][0] = X;
                goto flag1;
            }
            else if (board[i][0] == board[i][2] && board[i][2] == X && board[i][1] ==  )
            {
                board[i][1] = X;
                goto flag1;
            }
            else if (board[0][i] == board[1][i] && board[0][i] == X && board[2][i] ==  )
            {
                board[2][i] = X;
                goto flag1;
            }
            else if (board[1][i] == board[2][i] && board[1][i] == X && board[0][i] ==  )
            {
                board[0][i] = X;
                goto flag1;
            }
            else if (board[0][i] == board[2][i] && board[2][i] == X && board[1][i] ==  )
            {
                board[1][i] = X;
                goto flag1;
            }
            else if (board[0][0] == board[1][1] && board[0][0] == X && board[2][2] ==  )
            {
                board[2][2] = X;
                goto flag1;
            }
            else if (board[1][1] == board[2][2] && board[1][1] == X && board[0][0] ==  )
            {
                board[0][0] = X;
                goto flag1;
            }
            else if (board[0][0] == board[2][2] && board[0][0] == X && board[1][1] ==  )
            {
                board[1][1] = X;
                goto flag1;
            }
            else if (board[0][2] == board[1][1] && board[1][1] == X && board[2][0] ==  )
            {
                board[2][0] = X;
                goto flag1;
            }
            else if (board[1][1] == board[2][0] && board[1][1] == X && board[0][2] ==  )
            {
                board[0][2] = X;
                goto flag1;
            }
            else if (board[2][0] == board[0][2] && board[2][0] == X && board[1][1] ==  )
            {
                board[1][1] = X;
                goto flag1;
            }
        }
        for (i = 0; i < rows; i++)
        {
            if (board[i][0] == board[i][1] && board[i][0] == O && board[i][2] ==  )
            {
                board[i][2] = X;
                goto flag1;
            }
            else if (board[i][1] == board[i][2] && board[i][1] == O && board[i][0] ==  )
            {
                board[i][0] = X;
                goto flag1;
            }
            else if (board[i][0] == board[i][2] && board[i][2] == O && board[i][1] ==  )
            {
                board[i][1] = X;
                goto flag1;
            }
            else if (board[0][i] == board[1][i] && board[0][i] == O && board[2][i] ==  )
            {
                board[2][i] = X;
                goto flag1;
            }
            else if (board[1][i] == board[2][i] && board[1][i] == O && board[0][i] ==  )
            {
                board[0][i] = X;
                goto flag1;
            }
            else if (board[0][i] == board[2][i] && board[2][i] == O && board[1][i] ==  )
            {
                board[1][i] = X;
                goto flag1;
            }
            else if (board[0][0] == board[1][1] && board[0][0] == O && board[2][2] ==  )
            {
                board[2][2] = X;
                goto flag1;
            }
            else if (board[1][1] == board[2][2] && board[1][1] == O && board[0][0] ==  )
            {
                board[0][0] = X;
                goto flag1;
            }
            else if (board[0][0] == board[2][2] && board[0][0] == O && board[1][1] ==  )
            {
                board[1][1] = X;
                goto flag1;
            }
            else if (board[0][2] == board[1][1] && board[1][1] == O && board[2][0] ==  )
            {
                board[2][0] = X;
                goto flag1;
            }
            else if (board[1][1] == board[2][0] && board[1][1] == O && board[0][2] ==  )
            {
                board[0][2] = X;
                goto flag1;
            }
            else if (board[2][0] == board[0][2] && board[2][0] == O && board[1][1] ==  )
            {
                board[1][1] = X;
                goto flag1;
            }
        }
        if (board[x][y] ==  )
        {
            board[x][y] = X;
            goto flag1;
        }
    }
flag1:;
}

void player_move(char board[ROWS][COLS], int rows, int cols)
{
    int x, y;
    printf("Player‘s turn to move:\n");
    while (1)
    {
        printf("Input x and y(like x y):\n");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= rows && y >= 1 && y <= cols)
        {
            if (board[x - 1][y - 1] ==  )
            {
                board[x - 1][y - 1] = O;
                break;
            }
            else printf("The location has been taken!Please try again.\n");
        }
        else printf(" Input error!Please try again.\n");
    }
}

static int is_full(char board[ROWS][COLS], int rows, int cols)
{
    int i, j;
    for (i = 0; i < rows; i++)
    {
        for (j = 0; j < cols; j++)
        {
            if (board[i][j] ==  )
                return 0;
        }
    }
    return 1;
}

char check_win(char board[ROWS][COLS], int rows, int cols)
{
    int i;
    for (i = 0; i < rows; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] !=  )
            return board[i][1];
    }
    for (i = 0; i < cols; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] !=  )
            return board[1][i];
    }
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] !=  )
        return board[1][1];
    else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] !=  )
        return board[1][1];
    else if (is_full(board, rows, cols))
        return q;
    return 0;
}

这一部分是经过发挥的,让电脑更智能,但代码部分我并没有想出简化的写法,只好一步步的用if语句进行完成了。

第三部分是源文件的游戏测试部分:

#include"3chess.h"
void menu()
{
    printf("***************************************\n");
    printf("*      1.play             0.exit      *\n");
    printf("***************************************\n");
}
void first_move()
{
    printf("***************************************\n");
    printf("*  1.computer first   2.player first  *\n");
    printf("***************************************\n");
}
void game()
{
    int choice_1, win;
    char board[ROWS][COLS];
    init_board(board, ROWS, COLS);
    first_move();
flag:
    printf("Input your choice;");
    scanf("%d", &choice_1);
    switch (choice_1)
    {
    case 1:
        do
        {
            computer_move(board, ROWS, COLS);
            show_board(board, ROWS, COLS);
            win = check_win(board, ROWS, COLS);
            if (win != 0)
                break;
            player_move(board, ROWS, COLS);
            show_board(board, ROWS, COLS);
            win = check_win(board, ROWS, COLS);
        } while (win == 0);
        if (win == X)
            printf("You lose!Good luck next time!\n");
        if (win == O)
            printf("You win!Congratulations!\n");
        if (win == q)
            printf("The score was tied!Good luck next time!\n");
        break;
    case 2:
        do
        {
            show_board(board, ROWS, COLS);
            player_move(board, ROWS, COLS);
            show_board(board, ROWS, COLS);
            win = check_win(board, ROWS, COLS);
            if (win != 0)
                break;
            computer_move(board, ROWS, COLS);
            win = check_win(board, ROWS, COLS);
        } while (win == 0);
        if (win == X)
            printf("You lose!Good luck next time!\n");
        if (win == O)
            printf("You win!Congratulations!\n");
        if (win == q)
            printf("The score was tied!Good luck next time!\n");
        break;
    default:
        printf(" Input error!Please try again.\n");
        goto flag;
    }
}
int main()
{
    int choice;
    srand((unsigned int)time(NULL));
    do
    {
        menu();
        printf("Input your choice:");
        scanf("%d", &choice);
        switch (choice)
        {
        case 1:
            game();
            break;
        case 0:
            break;
        default:
            printf(" Input error!Please try again.\n");
            break;
        }
    } while (choice);
    return 0;
}

这一部分,我加入了让用户选择电脑先走或者用户先走的功能,使用户的游戏体验更好。

以上就是我的代码,希望各位能帮助我进行优化改进。

用C语言完成:三子棋。

标签:inpu   computer   bre   棋盘   二维   ini   开始   ==   简单的   

原文地址:http://www.cnblogs.com/xiefei777/p/7710856.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!