三子棋拿下!!!

学习前

想象特别美好,现实特别残酷,脑袋里感觉每个点都想到怎么写了,就打算自己试试,结果发现总会卡壳,直到学习了一下具体写法,真是大彻大悟。

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>

void Menu(void)
{
    printf("************************\n");
    printf("*******三子棋游戏*******\n");
    printf("************************\n");
    printf("*********play 1*********\n");
    printf("*********exit 0*********\n");
    printf("************************\n");
}
int Game()
{
    int a[3][3] = { 0 }, b = 0, c = 0;
    int b[3][3] = { 0 }, c[3][3] = 0;
    int i = 0, j = 0,k=0,l=0,m=0,n=0,part=0;
    printf("*********游戏开始喽*********\n");
    printf("双方轮流输入下棋位置\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) 
            printf("%d ", a[i][j]);
        printf("\n");
    }
    part++;
    if (part % 2 != 0) {
        scanf("%d%d\n", &k, &l);
        
            printf("\n");
        }
    }
    

    

int main()
{
    int a;
    do {
        Menu();
        scanf("%d", &a);
        switch (a)
        {
        case 0:goto byebye;
        case 1:goto again;
        }
    } while (1);
byebye:
    printf("Goodbye!\n");
again:
    Game();

    return 0;

步骤一 分析所写程序

1.可反复参与游戏、可自行退出

2.应用多文件写代码

test.c  游戏测试

game.c 游戏函数的实现

game.h 游戏函数的声明

pppps. 包含自己头文件形式  #include “game.h”

宏定义的使用:已知3*3二维数组一直不变/方便改想要的格数

3.需要3*3的二维数组存储数据

4.棋盘在每个阶段怎么设计

5.下棋时具体情况细节,能不能落子,玩家输错提示,重新输入

6.怎样设计之后方便更改(宏定义)

步骤二 写好主函数框架

int main()
{
    int input;
    srand((unsigned int)time(NULL));
    do {
        Menu();
        scanf("%d", &input);
        switch (input)
        {
        case 0:printf("退出游戏~下次见咯!\n");
            break;
        case 1:Game();
            break;
        default:printf("输入有误,请重新输入:\n");
        }
    } while (input);
    return 0;
}

步骤三 游戏实现文件

在这一部分中,我觉得比较难理解的是设计棋盘的部分和判断输赢部分,下面我来简略解释一下这两个部分:

Display_board

void Display_board(char board[ROW][COL], int row, int col)//棋盘设计
{
    int i, j;
    for (i = 0; i < ROW; i++)

{   

 //这个部分有两个列循环

//分别是数据打印和棋盘分割线打印

//打印数据行格式 “  %c | %c | %c  ” 上图中蓝绿色部分

//打印分割线格式 “ ---|----|--- ” 上图中黄色部分

//打印方式不唯一哦

 for (j = 0; j < COL; j++)
 {
     //打印数据
     printf(" %c ", board[i][j]);
     if (j < col - 1)//最后一个数据打印完无需“|”
         printf("|");//由列数控制
 }
     printf("\n");//容易遗忘
//打印分割线
    if (i < row - 1){
        int j;
        for (j = 0; j < col; j++) {
            printf("---");
            if (j < col-1 )
                printf("|");//和列数相关
        }
        printf("\n");
    }

  }
        printf("\n");  //切记每一行打印完都需要换行打印!!!
    
}

需要注意的点

1.每次落子后都需再次调用棋盘设计函数

2.无论是玩家下棋还是电脑下棋都要采取赋值的方式,直接打印棋子会导致如下情况

3.形参和实参不要搞混

4.注意参数定义范围,切忌重复定义

Is_Win

char Is_Win(char board[ROW][COL], int row, int col)
{

//整体思路 _主函数通过Is_Win 函数返回值来给用户反馈

//这个部分需要分为四个部分

//分别从行、列、对角线获胜 + 平局 + 未满足以上两种情况继续游戏

//行

 int i;
 for (i = 0; i < row; i++)
 {
     //行相等且都不为空才能满足赢的条件
     if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
         return board[i][0];//返回满足该条件的符号
 }

//列

int j = 0;
for (j = 0; j < col; j++)
{
    //列相等且都不为空才能满足赢的条件
    if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
        return board[0][j];//返回满足该条件的符号
}

//对角线

 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
     return board[0][0];
 else if (board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')
     return board[1][1];

//平局

//单独定义一个函数_我理解为方便定义变量

//避免变量重复定义或定义新变量的复杂情况

int Is_FULL(char board[ROW][COL], int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++)
    {
        int j;
        for (j = 0; j < col; j++)
        {
//判断有无落子区域
//有一个就返回0
//无落子区域则返回1
            if (board[i][j] == ' ')
                return 0;
        }
    }
    return 1;
} 
if (Is_FULL(board, row, col) == 1)
 {
     return 'Q';
}

//不满足以上任何一种情况 则返回 ' C '

 //当既不满足获胜条件也不满足无法落子情况,游戏继续
 return 'C';
 //继续

}

完整代码分享(欢迎交流讨论哦)

game.h

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3

//棋盘初始化
void Initboard(char board[ROW][COL], int row, int col);
//设计棋盘
void Display_board(char board[ROW][COL], int row, int col);
//玩家下棋
void Player_board(char board[ROW][COL], int row, int col);
//电脑下棋
void Computer_Player(char board[ROW][COL], int row, int col);
//判断输赢,返回相应符号
char Is_Win(char board[ROW][COL], int row, int col);
//判断是否还有落子区域
//这里重新建一个函数我认为是方便定义变量
//避免变量重复定义的复杂情况
int Is_FULL(char board[ROW][COL], int row, int col);

test.c

#define _CRT_SECURE_NO_WARNINGS 
#include "game.h"
#define ROW 3
#define COL 3
void Menu(void)
{
    printf("************************\n");
    printf("*******三子棋游戏*******\n");
    printf("************************\n");
    printf("*********play 1*********\n");
    printf("*********exit 0*********\n");
    printf("************************\n");
}
int Game()//游戏实现
{
    char board[ROW][COL] = { 0 };
    Initboard(board,ROW ,COL);
    Display_board(board, ROW, COL);
    char ret = 0;
    while (1)
    {
        //玩家下棋
        Player_board(board, ROW, COL);
        Display_board(board, ROW, COL);
        //判断输赢
        ret=Is_Win(board, ROW, COL);//返回一个值,再判断
        if (ret != 'C')
            break;
        //计算机下棋
        Computer_Player(board, ROW, COL);
        Display_board(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");
    
}
int main()
{
    int input;
    srand((unsigned int)time(NULL));
    do {
        Menu();
        scanf("%d", &input);
        switch (input)
        {
        case 0:printf("退出游戏~下次见咯!\n");
            break;
        case 1:Game();
            break;
        default:printf("输入有误,请重新输入:\n");
        }
    } while (input);
    return 0;
}

注意!

无论是玩家下棋还是电脑下棋,都牵涉输赢情况的改变,所以每次下完都需要返回一次Is_Win的值

game.c 

#define _CRT_SECURE_NO_WARNINGS 
#include "game.h"
#include <stdio.h>
//游戏中应用到的代码
void Initboard(char board[ROW][COL],int row,int col)//棋盘初始化
{
    int i ,j;
    for (i = 0; i < row; i++)
        for (j = 0; j < col; j++)
            board[i][j] = ' ';

}
void Display_board(char board[ROW][COL], int row, int col)//棋盘设计
{
    int i, j;
    for (i = 0; i < ROW; i++) {
        for (j = 0; j < COL; j++)
        {
            //打印数据
            printf(" %c ", board[i][j]);
            if (j < col - 1)//最后一个数据打印完无需“|”
                printf("|");//由列数控制
        }
            printf("\n");//容易遗忘
        //打印分割线
            if (i < row - 1){
                int j;
                for (j = 0; j < col; j++) {
                    printf("---");
                    if (j < col-1 )
                        printf("|");//和列数相关
                }
                printf("\n");
            }
        }
        printf("\n");
    
}
void Player_board(char board[ROW][COL], int row, int col)
{
    int x=0, y=0;
    printf("玩家下棋>\n");
    while (1)
    {
        printf("请输入下棋坐标:\n");
        scanf("%d %d", &x, &y);
        /*if (sizeof(x) != sizeof(int) || sizeof(y) != sizeof(int))
        {
            printf("输入格式错误,请重新输入\n");
            break;
        }*/
        if (x >= 1 && x <= row && y >= 1 && y <= col)//玩家输入合法 
        {
            if (board[x - 1][y - 1] == ' ')//是否有空位可以落子
            { 
               // printf("*", board[x - 1][y - 1]); break;//错误写法,会使棋盘错位
                board[x - 1][y - 1] = '*'; break;//一定要记得break否则会陷在此函数,棋盘消失
            }
            else
                printf("此位置已被占用,请重新输入!\n");
        }
        else//不合法
        {
            printf("输入非法,请重新输入\n");
        }
    }
}
void Computer_Player(char board[ROW][COL], int row, int col)
{
    //电脑下棋
    int x = 0, y = 0;
    printf("电脑下棋>\n");
    while (1) //一直生成随机数,直到满足落子条件
    {
        x = rand() % row;//生成随机数
        y = rand() % col;
        if (board[x][y] == ' ')//判断能否落子
        {
            board[x][y] = '#';//一定要采用赋值哦,不然棋盘会错位
            break;
        }
    }
}
int Is_FULL(char board[ROW][COL], int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++)
    {
        int j;
        for (j = 0; j < col; j++)
        {
            if (board[i][j] == ' ')//判断有无落子区域有一个就返回0都无则返回1
                return 0;
        }
    }
    return 1;
}
char Is_Win(char board[ROW][COL], int row, int col)
{
//行
    int i;
    for (i = 0; i < row; i++)
    {
        //行相等且都不为空才能满足赢的条件
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
            return board[i][0];//返回满足该条件的符号
    }
    //列
    int j = 0;
    for (j = 0; j < col; j++)
    {
        //列相等且都不为空才能满足赢的条件
        if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
            return board[0][j];//返回满足该条件的符号
    }
    //对角线
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
        return board[0][0];
    else if (board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')
        return board[1][1];
    //判断是否还有落子区域
    if (Is_FULL(board, row, col) == 1)
    {
        return 'Q';
   }
    
    //当既不满足获胜条件也不满足无法落子情况,游戏继续
    return 'C';
    //继续
}

期待和大家的交流哦~ 

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值