有趣的代码——井字棋游戏的实现尝试版

前面我们讲解过一个猜数字游戏的实现,想来应该让大家感受到了属于编程的趣味性,并且在实现过程中应该也收获了知识。但猜数字这种简单的游戏肯定满足不了大家对于游戏的高标准、严要求,估计玩不了多久就会没有兴趣了,所以,今天在这里和大家分享一个更好玩,也更有实现难度的小游戏——井字棋!相信大家都不会对这个游戏陌生的(可能有朋友不久前还在学校和小伙伴一起玩呢),那么今天就让我们一起通过编程把这个小游戏实现吧。

1.井字棋游戏的大致流程

首先,由计算机产生一个3*3大小的棋盘,并显示玩家和计算机各自使用的棋子,然后由玩家、计算机轮流在上面落子,哪一方先3颗棋子连成一条线,则显示该方获胜,如果棋局填满,还没有一方三子连线,则判定为和棋。

2.游戏实现的思路

还记得我在猜数字游戏的实现中说过的一句话吗?没错,我们在写编程题或者小游戏代码时,最重要的就是理清实现思路——主体是什么?为了实现目的要创建哪些函数?函数的功能都是什么?只有当我们心中有了一个大体的框架,知道该做些什么时,我们才能更高效地编写代码,完成程序设计。

井字棋游戏的算法如下:

1.提供游戏菜单,由玩家选择是否进行游戏:按“1”开始游戏,按“0”退出游戏,按其他则显示“选择错误,请重新选择”。

2.打印未放置任何棋子的棋盘,并显示玩家和计算机分别分配的棋子类型,并提示玩家先下棋。

        2.1PlayerMove(玩家下棋),在棋盘上显示位置,并ret=IsWin(判断是否胜利)。

        2.2ComputerMove(电脑下棋)在棋盘上显示位置,并ret=IsWin(判断是否胜利)。

        2.3根据ret(定义判断结果的变量)判断最终结果,若玩家胜利,则显示“亲爱的玩家,恭喜你获得游戏胜利!”;若电脑胜利,则显示“亲爱的玩家,请不要因失败而气馁,期待你的下一次开始!”;若平局,则显示“亲爱的玩家,该局游戏平局!”

3.本轮游戏结束,打印游戏菜单并再次询问玩家选择。

二、程序框架
我们将游戏的源文件和头文件分为三个部分,分别是:game.h 、test.c 、game.c

1. game.h        
在game.h中为所有需要用到的库函数的头文件的声明,以及要在test.c源文件中使用需要在game.h中定义的自定义函数的声明。

2.test.c
test.c为游戏的整体逻辑部分,并引用头文件"game.h"。

3.game.c
game.c为游戏的实现部分,也要引用头文件"game.h"。

在解决方案资源管理器中找到源文件和头文件的文件夹,分别再头文件文件夹中创建game.h头文件以及在源文件文件夹中创建test.c、game.c两个源文件。

三、游戏实现
1.test.c中编辑游戏的整体逻辑
1-1.创建主函数
int main() //创建主函数
{
    srand((unsigned)time(NULL)); //生成随机数随机数(后面用到)
    test(); //在test();中实现游戏逻辑,让主函数更简洁
 
    return 0;
}
 1-2.定义test()函数
void test() //定义test();函数
{
    int input = 0;
    do
    {
        menu();  //打印菜单
 
        //选择游戏进程
 
        printf("请输入:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();  //实现游戏逻辑
            break;
        case 0:
            printf("游戏结束\n");
            break;
        default:
            printf("输入错误!!!(请重新输入1 or 0)\n");
            break;
        }
 
    } while (input); //每次游戏结束后让玩家选择,当玩家输入1为真游戏继续并开始,输入0为假退出循                                                                
                     // 环,游戏结束。
}

1-3.定义menu()函数
void menu()
{
    printf("***********************\n");
    printf("****    1. play    ****\n");
    printf("****    0. exit    ****\n");
    printf("***********************\n");
 
}
1-4.定义game()函数
void game()
{
    //创建棋盘
    char board[ROW][COL] = { 0 };
    //棋盘初始化
    InitBoard(board, ROW, COL);
    //打印棋盘
    DisplayBoard(board, ROW, COL);
    char ret = 0;
    while (1)
    {
        //玩家回合
        Player_Move(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        //判断结束或继续
        ret = Is_Win(board, ROW, COL);
        if (ret != 'C')
            break;
        //电脑回合
        Computer_Move(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        ret = Is_Win(board, ROW, COL);
        if (ret != 'C')
            break;
    }
    //判断输赢
    if (ret == '*')
        printf("玩家赢\n");
    else if (ret == '#')
        printf("电脑赢\n");
    else
        printf("平局\n");
}

以下为test.c源文件的整体逻辑

#include "game.h"
 
//打印菜单
void menu()
{
    printf("***********************\n");
    printf("****    1. play    ****\n");
    printf("****    0. exit    ****\n");
    printf("***********************\n");
 
}
 
 
//游戏实现
void game()
{
    //创建棋盘
    char board[ROW][COL] = { 0 };
    //棋盘初始化
    InitBoard(board, ROW, COL);
    //打印棋盘
    DisplayBoard(board, ROW, COL);
    char ret = 0;
    while (1)
    {
        //玩家回合
        Player_Move(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        //判断结束或继续
        ret = Is_Win(board, ROW, COL);
        if (ret != 'C')
            break;
        //电脑回合
        Computer_Move(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        ret = Is_Win(board, ROW, COL);
        if (ret != 'C')
            break;
    }
    //判断输赢
    if (ret == '*')
        printf("玩家赢\n");
    else if (ret == '#')
        printf("电脑赢\n");
    else
        printf("平局\n");
}
 
void test()
{
    int input = 0;
    do
    {
        //打印菜单
        menu();
        //选择游戏进程
        printf("请输入:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("游戏结束\n");
            break;
        default:
            printf("输入错误!!!(请重新输入1 or 0)\n");
            break;
        }
 
    } while (input);
}
 
int main()
{
    //随机数
    srand((unsigned)time(NULL));
    test();
 
    return 0;
}

2.game.h头文件部分的内容
头文件中包含对库函数、自定义函数的声明。

#pragma once
 
//头文件声明
#include
#include
#include
 
//定义宏常量
#define ROW 3
#define COL 3
 
//函数声明
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void Player_Move(char board[ROW][COL], int row, int col);
void Computer_Move(char board[ROW][COL], int row, int col);
 
//char返回类型
//若返回"*"则玩家获胜
//若返回"#"则玩家获胜
//若返回"D"(draw)则平局
//若返回"C"(continue)游戏继续
char Is_Win(char board[ROW][COL], int row, int col);
 
int Is_Full(char board[ROW][COL], int row, int col);

3.game.c 游戏逻辑的实现
game.c是对test.c中game()函数中所使用的函数的定义。

3-1.InitBoard() 自定义的棋盘初始化函数  对九个棋盘格进行初始化为空格
//棋盘初始化
//void 空型函数,char board[ROW][COL]二维数组接收指针,int row、int col接收ROW\COL的形参
void InitBoard(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++) //用for循环语句对二维数组进行初始化
    {
        for (j = 0; j < col; j++)
        {
            board[i][j] = ' ';
        }
    }
}
3-2.打印棋盘
//棋盘打印
//此方式打印出来的棋盘,可以通过对COW和COL宏常量的修改来改变棋盘大小
void DisplayBoard(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            printf(" %c ", board[i][j]);
            if (j < col - 1)
                printf("|");
        }
        printf("\n");
        for(j = 0; j < col; j++)
        {
            if (i < row - 1)
            {
                printf("---");
                if (j < col - 1)
                    printf("|");
            }
        }
            printf("\n");
    }
}

3-3.玩家回合下棋
//玩家回合
void Player_Move(char board[ROW][COL], int row, int col)
{
    printf("玩家回合\n");
    int x = 0;
    int y = 0;
    while (1)
    {
        printf("请输入:>");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)
        {
            if (board[x - 1][y - 1] == ' ')
            {
                board[x - 1][y - 1] = '*';
                break;
            }
            else
            {
                printf("该位置已被占用!!!\n");
            }
        }
        else
        {
            printf("输入错误!!!(请重新输入1 ~ 3)\n");
        }
    }
}

3-4.电脑回合下棋
void Computer_Move(char board[ROW][COL], int row, int col)
{
    printf("电脑回合\n");
    while (1)
    {
        int x = rand() % row;  //rand()与之前的主函数中srand()共同调用生成随机数
        int y = rand() % col;
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }
}
3-5.判断游戏的输赢
//判断游戏是否结束
char Is_Win(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 1; j < col; j++)
        {
            if (board[i][j - 1] == board[i][j] && board[i][j] == board[i][j + 1] && board[i][j] != ' ')
                return board[i][j];
        }
    }
    for (j = 0; j < col; j++)
    {
        for(i = 1; i < row - 1; i++)
            if (board[i - 1][j] == board[i][j] && board[i][j] == board[i + 1][j] && board[i][j] != ' ')
                return board[i][j];
    }
    for (i = 1; i < row - 1; i++)
    {
        for (j = 1; j < col - 1; j++)
        {
            if (board[i - 1][j - 1] == board[i][j] && board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ')
                return board[i][j];
            if (board[i - 1][j + 1] == board[i][j] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ')
                return board[i][j];
        }
    }
    if (1 == Is_Full(board, row, col))
        return 'D';
    else
        return 'C';
}
 
//判断棋盘是否下满
int Is_Full(char board[ROW][COL], int row, int col)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (board[i][j] == ' ')
                return 0;
        }
    }
    return 1;
}

到这里我们就完成对井字棋的实现了,电脑的下棋是随机的,会类似于人工智障的效果。

你可能感兴趣的:(游戏)