鱼C论坛

 找回密码
 立即注册
查看: 1960|回复: 2

[技术交流] 【C语言练习项目】三子棋

[复制链接]
发表于 2021-8-25 18:45:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 超过光速c 于 2021-8-25 18:47 编辑

三子棋游戏!!
三个文件,先直接贴上来。

test_.c  文件的内容
/**
 * @file test_.c
 * @date 2021-08-24
 * 
 * 三子棋
 * 
 */

#include "game_3.h"
#include "game_3.c"

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

}

// 游戏的整个算法实现
void game_3(){
    char ret;
    // 数组-存放走出的棋盘信息
    char board[ROW][COL] = {0};  // 全部空格,初始化一下棋盘,即初始化数组
    // 初始化棋盘
    InitBoard(board, ROW, COL);

    // 打印棋盘
    DisplayBoard(board, ROW, COL);

    //下棋
    while(1){
        // 玩家下棋
        PlayerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        // 判断玩家是否赢
        ret = IsWin(board, ROW, COL);
        if(ret != 'C') {
            break;
        }
        // 电脑下棋
        ComputerMove(board, ROW, COL);
        DisplayBoard(board, ROW, COL);
        // 判断电脑是否赢
        ret = IsWin(board, ROW, COL);
        if(ret != 'C') {
            break;
        }
    }
    if (ret == '*')
    {
        printf("玩家赢了\n");
    }
    else if (ret == '#')
    {
        printf("电脑赢了\n");
    }
    else
    {
        printf("平局!\n");
    }


}


void test_(){
    int input=0;
    // 随机存储生成器
    srand((unsigned int)time(NULL));

    do{
        menu();
        printf("请选择 : >> ");
        scanf("%d",&input);
        switch(input){
            case 1:
                game_3();
                // printf("开始游戏!\n");
                break;
            case 0:
                printf("退出游戏!\n");
                break;
            default:
                printf("输入错误,请重新输入:");
                break;
        }
    }while(input);
}

int main(){

    test_();

    printf("\n");
    return 0;
}


game_3.c 文件内容
#include "game_3.h"


// 实现初始化
void InitBoard(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++){
            board[i][j] = ' ';
        }
    }

}

// 实现打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col){
    int i = 0;
    int j = 0;
    for(i=0;i<row;i++){
        // 1.打印第一行数据
        for(j=0;j<col;j++){
            printf(" %c ",board[i][j]);
            if(j < col-1) printf("|");
        }
        printf("\n");
        // printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);
        // 2.打印分割行

        if(i < row-1){
            for(j=0;j<col;j++){
            printf("---");
            if(j < col-1) printf("|");
            }

            printf("\n");
        }
            // printf("---|---|---\n");
    }
}

// 实现玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col){
    int x=0, y=0;

    printf("玩家走:> \n");
    while(1){
        printf("请输入要下的坐标:>");
        scanf("%d%d",&x,&y);
        getchar();

        // 判断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("坐标非法,请重新输入!");
        }
    }

}

// 实现电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col){
    int x=0;
    int y=0;
    printf("电脑走!\n");

    while(1){
        x = rand() % row;
        y = rand() % col;
        
        if(board[x][y] == ' '){
            board[x][y] = '#';
            break;
        }
    }
}


// 满了返回1,没满返回0
int IsFull(char board[ROW][COL], int row, int col)
{
    for(int j=0;j<row;j++)
    {
        for(int i=0;i<col;i++)
        {
            if(board[i][j] == ' ')
            {
                return 0; // 没满
            }
        }
    }
    return 1; // 满了
}

// 实现判断输赢
char IsWin(char board[ROW][COL], int row, int col){
    // 判断行
    for(int i = 0; i < row; i++){
        if(board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
        {
            return board[i][1];
        }
    }

    // 判断列
    for(int i = 0; i < col; 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];
    }
    if(board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
    {
        return board[1][1];
    }

    // 判断平局
    if(1 == IsFull(board, ROW, COL))
    {
        return 'Q';
    }
    return 'C';
}


game_3.h 文件内容
#define ROW 3
#define COL 3

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

// #include "game_3.c"

// 声明
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);


// 告诉我门四种游戏状态,玩家赢 * 、电脑赢 #、平局 Q、继续 C
char IsWin(char board[ROW][COL], int row, int col);


/**
 * 整体逻辑回顾
 * 
 * 1、游戏便于循环玩,所以将所有操作包含在一个 do while 循环内
 *  -- 先打印选择目录,用户选择输入 1开始游戏,0退出游戏(退出循环)
 *  -- 对输入有一个检验,若输入错误则提示用户重新输入
 * 2、游戏的操作
 *  -- 用一个二维数组来存储棋盘
 *  -- 初始化棋盘,再将棋盘打印出来。利用for循环将棋盘拆分成每一个单独的元素进行遍历打印,更加的灵活
 *  -- 用户下棋:提示用户输入坐标,检验输入的坐标有效性,1、是否输入错误数值;2、输入坐标是否被占用。将坐标数组添加*号
 *  -- 电脑下棋:使用随机数值,检验坐标是否被占用。将坐标数组添加#号       随机存储生成器不理解?
 *  -- 每次走一步后将棋盘打印输出,观察走棋后的结果
 * 3、判断输赢
 *  -- 横、纵、交叉的坐标数组内相等,且任意一个坐标不等于‘ ’值(棋盘初始化为' '空值),就返回此前坐标数组内的符号,返回*则玩家赢,返回#则电脑赢
 *  -- 检验棋盘空格数。循环遍历检验每一个坐标数组,若满则返回为平局,若未满则继续游戏
 * 
 * 
 * 学得:
 * C语言,随机存储生成器,随机数的使用
 * rand() 函数包含于 <stdlib.h> 头文件中【random() 函数不是一个标准函数,无法再VC/VS等编译器通过。】
 * rand() 会随机产生一个位于 0~RAND_MAX(至少是32767)之间的整数
 * 伪随机数,根据电脑启动时而定,则不再变化。随机存储生成器:srand((unsigned)time(NULL)),根据时间进行随机产生新的数值
 * 随机数的范围设定:
 * rand() % 10 即 0~9
 * rand() % 51 + 13 即 13~63。rand()%51 即0~50,+13则是 0+13~50+13 即 13~63
 * 
 * 连续随机数的产生
 * 用for循环产生的都是一样的随机数
 * for(int i=0; i<10; i++) 
 * {
 *      srand((unsigned)time(NULL));
 *      a[i] = rand() % 100;
 *      printf("%d", a[i]);
 * }
 * 
 * 
 * 关于头文件 #include "" 和 <> 的区别用法,调取其他文件的函数
 * <> : 到库里面寻找头文件
 * "" : 优先到当前目录下寻找,找不到再到库里面取找。尽量优先使用,减少寻找所占用的资源。
 */

效果是这样的:
Screen Shot 2021-08-25 at 6.47.28 PM.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-8-26 10:15:37 | 显示全部楼层
学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-8-26 21:13:15 | 显示全部楼层

回帖奖励 +1 鱼币

学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-18 07:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表