0615, 函数,扔骰子,德州扑克(简易版)

目录

        第四章(表达式),第五章(语句),第六章(数组)思维导图

题目一 :扔骰子

解答01_有BUG:

解答02:

答案:

题目二 :德州扑克

解答/不对的挣扎:

答案:

题目三:简答题(外部变量,局部变量),FIBNACCI

解答:​​​​​​​

题目一 :扔骰子

编写程序模拟掷骰子的游戏(两个骰子)。每局游戏的规则如下:

第一次掷的时候,如 果点数之和为 7 或 11 则获胜;如果点数之和为2、3或12则落败;其他情况下的点数之和称为“目标”,游戏继续。在后续的投掷中,如果玩家再次掷出“目标”点数则获胜,掷出7则落败,其他情况都忽略,游戏继续进行。

每局游戏结束时,程序询问用户是否再玩一次,如果用 户输入的回答不是 y 或 Y ,程序会显示胜败的次数然后终止。(拓展题,不要求每个同学回答)

You rolled: 8
Your point is 8
You rolled: 3
You rolled: 10
You rolled: 8
You win!

Play again? y

You rolled: 6
Your point is 6
You rolled: 5
You rolled: 12
You rolled: 3
You rolled: 7
You lose!

Play again? y

You rolled: 11
You win!

Play again? n

Wins: 2 Losses: 1

解答01_有BUG:

BUG:while ((again = getchar()) == 'y' || (again = getchar()) == 'Y');
改正:scanf(" %c",&again);//不能忽略空格,否则会造成交互错误

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

int roll_dices();
int play_game(int a,int point,int count);

int main(void) {
	srand(time(NULL));
	char again;
	int wins = 0; int losses = 0; int dices=0;

	do {
		//一局游戏的内部循环
		int count=0 ; int point;
		int com_game = 0;
		do {
			point = dices;
			dices = roll_dices();
			printf("You rolled:%d\n", dices);
			com_game = play_game(dices, point, count);
			switch (com_game) {
			case 0:
				count++;
				break;
			case 1:
				printf("You win!\n");
				wins++;
				break;
			case 2:
				printf("You lose!\n");
				losses++;
				break;
			}
		} while (com_game==0);

		printf("Play again?\n");

	} while ((again = getchar()) == 'y' || (again = getchar()) == 'Y');
	
	printf("Wins: %d Losses: %d\n",wins,losses);
	return 0;
}


int roll_dices() {
	int random_num = 2 + rand() % 10;
	return random_num;
}
int play_game(int a, int point, int count) {
	if(count==0){
		if (a == 7 || a == 11) {
			return 1;
		}
		else if (a == 2 || a == 3 || a == 12) {
			return 2;
		}
		else {
			printf("Your point is %d\n", a);
			return 0;
		}
	}
	else if(count!=0){
		if (a == point) {
			return 1;
		}
		else if (a == 7) {
			return 2;
		}
		else {
			return 0;
		}
	}
}

解答02:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

int roll_dices();
int play_game(int a,int point,int count);

int main(void) {
	srand(time(NULL));
	char again='y';
	int wins = 0; int losses = 0; int dices=0;

	do {
		//一局游戏的内部循环
		int count=0 ; int point;
		int com_game = 0;
		do {
			point = dices;
			dices = roll_dices();
			printf("You rolled:%d\n", dices);
			com_game = play_game(dices, point, count);
			switch (com_game) {
			case 0:
				count++;
				break;
			case 1:
				printf("You win!\n");
				wins++;
				break;
			case 2:
				printf("You lose!\n");
				losses++;
				break;
			}
		} while (com_game==0);

		printf("Play again?\n");
		scanf(" %c",&again);

	} while (again=='y'||again=='Y');//(again = getchar()) == 'y' || (again = getchar()) == 'Y'//使用了两次GETCHAR,可能导致逻辑错误或影响交互体验
	
	printf("Wins: %d Losses: %d\n",wins,losses);
	return 0;
}


int roll_dices() {
	int random_num = 2 + rand() % 10;
	return random_num;
}
int play_game(int a, int point, int count) {
	if(count==0){
		switch (a) {
		case 7:case 11:
			return 1;
		case 2:case 3:case 12:
			return 2;
		default:
			printf("Your point is %d\n", a);
			return 0;
		}
	}
	else if(count!=0){
		if (a == point) {
			return 1;
		}
		else if (a == 7) {
			return 2;
		}
		else {
			return 0;
		}
	}
}

答案:

do {
        play_game() ? wins++ : losses++;      //play_game返回一个布尔值,条件运算符
        // 询问玩家是否继续
        printf("\nPlay agiain? ");
        // 读取第一个非空白字符             
        scanf(" %c", &again);         
        // 跳过这一行剩余字符         //可能是YES跳过ES!!!!
        while (getchar() != '\n')      

            ;
    } while (again == 'Y' || again == 'y');

#define _CRT_SECURE_NO_WARNINGS

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

bool play_game(void);
int roll_dice(void);

int main(void) {
	int wins = 0, losses = 0;
	char again;
	do {
		play_game() ? wins++ : losses++;
		// 询问玩家是否继续
		printf("\nPlay agiain? ");
        // 读取第一个非空白字符
		scanf(" %c", &again);
        // 跳过这一行剩余字符
		while (getchar() != '\n')
			;
	} while (again == 'Y' || again == 'y');

	printf("\nWins: %d Losses: %d\n", wins, losses);

	return 0;
}

bool play_game(void) {
	// 设置随机种子
	srand(time(NULL));

	int point = roll_dice();
	if (point == 7 || point == 11) {
		printf("You win!\n");
		return true;
	}
	if (point == 2 || point == 3 || point == 12) {
		printf("You lose!\n");
		return false;
	}

	printf("Your point is %d\n", point);

	for (;;) {
		int tally = roll_dice();
		if (tally == point) {
			printf("You win!\n");
			return true;
		}
		if (tally == 7) {
			printf("You lose!\n");
			return false;
		}
	}
}

int roll_dice() {
	int a = rand() % 6 + 1;
	int b = rand() % 6 + 1;
	printf("You rolled: %d\n", a + b);

	return a + b;
}

题目二 :德州扑克

(拓展题,不要求每个同学都作答) 德州扑克:写一个程序循环读取 5 张手牌 (输入 0 结束程序),然后把手中的牌分为下面某一类:1.同花顺 2.四张 3.葫芦 (3 + 2) 4. 同花 5. 顺子 6.三张 7.两对 8. 一对 9.高牌。

同花顺(Straight Flush): 五张同花色的连续数字牌,如红桃10-J-Q-K-A.

四张(Four of a Kind): 四张相同数字的牌,加一张其他数字的牌,如 A-A-A-A-K

葫芦(Full house): 三张相同数字的牌,加上一对其他数字的牌,如 A-A-A-K-K

同花(Flush): 五张同花色的牌,但不是顺子,如红桃 2-5-7-8-K

顺子(Straight): 由五张连续数字的牌组成 (简单起见,A-2-3-4-5 不是顺子),但不是同花。 如 2-3-4-5-6, 但包含不同花色的牌。

三张(Three of a kind): 由三张相同数字的牌,加两张不同数字的牌组成。如 A-A-A-2-K

两对(Two pair): 由两对加上一张杂牌组成。如 A-A-K-K-2

对子(Pair): 由一对加上三张不同的牌组成。如 A-A-5-6-K

高牌(High card): 无法组成上述任一牌型的杂牌。如 2-5-8-10-Q,且包含多种花色的牌。

程序对话如下:

Enter a card: 2s
Enter a card: 5s
Enter a card: 4s
Enter a card: 3s
Enter a card: 6s
Straight flush

Enter a card: 8c
Enter a card: as
Enter a card: 8c
Duplicate card; ignored.
Enter a card: 7c
Enter a card: ad
Enter a card: 3h
Pair

Enter a card: 6s
Enter a card: d2
Bad card; ignored.
Enter a card: 2d
Enter a card: 9c
Enter a card: 4h
Enter a card: ts
High card

Enter a card: 0

解答/不对的挣扎:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>   
#include <stdbool.h> 
#include <time.h>  
#define SIZE(a) (sizeof(a)/sizeof(a[0]))

int get_end(int same_ranks[],int max_ranks, int min_rank, int same_suits, int len);

int main(void) {
	const char rank[] = { '1','2','3','4','5','6','7','8','9','t','j','q','k','a' };
	const char suit[] = { 'd','c','h','s' };
	int result_rank[5];//记录牌号
	int result_suit[5];
	bool is_hand[13][4] = { false };
	char my_rank, my_suit;
	int num = 5;
	int i; int j; //for循环参数
	for (; ;) {
		for (;num!=0;) {
			scanf(" %c %c", &my_rank, &my_suit);
			if (my_rank == '0') {
				exit(0);
			}
			for (i = 0; i < SIZE(rank); i++)
			{
				for (j = 0; j < SIZE(suit); j++)
				{
					if (my_rank == rank[i] && my_suit == suit[j] && num != 0)
					{
						if (is_hand[i][j] == false)
						{
							is_hand[i][j] = true;
							result_rank[num] = i;  //记录牌号0-12
							result_suit[num] = j;   //0-3
							//printf("%d-%d ", i, j);
							num--;
						}
						else if (is_hand[i][j] == true)
						{
							printf("Duplicate card; ignored.\n");
						}
						else
						{
							printf("Bad card; ignored.\n");
						}
					}
				}
			}
		}

		//记录了5组数组再开始下一步

		num = 5; //初始化NUM-循环
		int same_ranks[4] = { 0 };      //相同牌面数量
		int max_ranks= result_rank[0];  //最大牌面
		int min_rank = result_rank[0];  //最小牌面
		int same_suits = 0;             //相同花色——只需要考虑花色全部相同的情况
		for (i = 0; i < 5; i++) {       //解读五张牌RANK
			for (j = 0; j < 5-i; j++) {
				if (result_rank[i] == result_rank[j]) {
					same_ranks[i]++;
				}
			}
			max_ranks = max_ranks > result_rank[i] ? max_ranks : result_rank[i];
			min_rank = min_rank < result_rank[i] ? min_rank : result_rank[i];
		} 
		for (i = 0; i < 5; i++) {         //解读五张牌suit
			for (j = 0; j < 5 - i; j++) {
				if (result_suit[i] == result_suit[j]) {
					same_suits++;
				}
			}
		}
		//查看结果
		switch (get_end(same_ranks, max_ranks, min_rank,same_suits,4)) {
		case 1:
			printf("同花顺Straight Flush\n");
			break;
		case 2:
			printf("四条Four of a Kind\n");
			break;
		case 3:
			printf("葫芦(Full House)\n");
			break;
		case 4:
			printf("同花Flush\n");
			break;
		case 5:
			printf("顺子Straight\n");
			break;
		case 6:
			printf("三条(Three of a Kind)\n");
			break;
		case 7:
			printf("两对(Two Pair)\n");
			break;
		case 8:
			printf("一对(One Pair)\n");
			break;
		case 9:
			printf("高牌(High Card)\n");
			break;
		}
		//清零数组数据
		//is_hand[13][4] = { false };
	}
	return 0;
}


int get_end(int same_ranks[], int max_ranks, int min_rank, int same_suits, int len) {
	if ((max_ranks - min_rank == 4) || same_suits == 4) {
		return 1;
	}else if ((max_ranks - min_rank == 4) || same_suits != 4) {
		return 5;
	}
	else if ((max_ranks - min_rank != 4) || same_suits == 4) {
		return 4;
	}
	else {
		int same_max=same_ranks[0], same_min= same_ranks[0];
		int i;
		for (i = 1; i < len; i++) {
			same_max = same_max > same_ranks[i] ? same_max : same_ranks[i];
			same_min = same_min < same_ranks[i] ? same_min : same_ranks[i];
		}
		switch (same_max - same_min) {
		case 4:
			return 2; break;
		case 2:
			return 7; break;
		case 1:
			return 8; break;
		case 0:
			return 9; break;
		case 3:
			for (i = 0; i < len; i++) {
				if (same_ranks[i] == 2) {
					return 3; break;
				}
				else if (same_ranks[i] == 1) {
					return 6; break;
				}
			}
			break;
		}
	}
}



/*
4,同花(Flush):                                   //SUIT 相同,
1,同花顺(Straight Flush):任意花色的连续五张牌。    //RANK连续(最大的RANK标号-最小的==4),-suit相同
5,顺子(Straight):连续的五张牌。           //RANK连续(最大的RANK标号-最小的==4)  suit不定


2,四条(Four of a Kind):四张同等级的牌。          //RANK 4,1        4100  40 4
3,葫芦(Full House):三张同等级的牌加一对其他等级的牌。   //RANK 3-2    3200 30 3 
6,三条(Three of a Kind):三张同等级的牌。     //rank-3,1,1          3110  30 3
7,两对(Two Pair):两对不同等级的牌。      //rank-2,2,1             2210  20 2
8,一对(One Pair):一对同等级的牌。          //rank-2,1,1,1          2111  21 2-1=1
9,高牌(High Card):如果没有以上组合,则根据最高的单张牌判断胜负。*/   //rank 1,1,1,1,1,     1111 1-1=0 

答案:

int num_in_rank[13];      //读取牌面字符,CASE成数子,数组下标代表牌面,++
int num_in_suit[4];         //同上,数组下标代表数字,++,5同花,4张,3张,2张,遍历一次就行,return结束函数

bool straight, flush, four, three;         //唯一情况
int pairs;    /* can be 0, 1, or 2 */       //两种情况 2,2,1,需要++计数

全局变量,不需要传递参数

for ( ;; ) {
        read_cards();
        analyze_hand();
        print_result();
    }

void read_cards(void);     

//都会对前两个字符进行识别,剩余字符不是空白字符,算非法输入,然后写入信息

// 处理这一行的剩余字符
        while ((c = getchar()) != '\n') {  
            if (c != ' ' && c != '\t')
                bad_card = true;
        }

void analyze_hand(void);

//顺子分析:找到第一张出现的牌面,num_in_rank[i]不等于0的时候
//开始计数,到下一张不为0的牌面,int n_consective = 0;5是顺子

void print_result(void);

链接IF

#include <stdio.h>
#include <stdbool.h>

void read_cards(void);
void analyze_hand(void);
void print_result(void);

int num_in_rank[13];
int num_in_suit[4];

bool straight, flush, four, three;
int pairs;	/* can be 0, 1, or 2 */

int main(void) {
	for ( ;; ) {
		read_cards();
		analyze_hand();
		print_result();
	}
    
    return 0;
}

void print_result(void) {
	if (straight && flush) {
		printf("Straight flush\n");
	} else if (four) {
		printf("Four\n");
	} else if (three && (pairs == 1)) {
		printf("Full hourse\n");
	} else if (flush) {
		printf("Flush\n");
	} else if (straight) {
		printf("Straight\n");
	} else if (three && (pairs == 0)) {
		printf("Three\n");
	} else if (pairs == 2) {
		printf("Two pairs\n");
	} else if (pairs == 1) {
		printf("One pair\n");
	} else {
		printf("High card\n");
	}
    printf("\n");
}

void analyze_hand(void) {
	/* 初始化 */
	straight = false;
	flush = false;
	four = false;
	three = false;
	pairs = 0;

	/* 检查是否为同花 */
	for (int i = 0; i < 4; i++) {
		if (num_in_suit[i] == 5) {
			flush = true;
		}
	}

	/* 检查是否为顺子 */
	int idx = 0;
	while (num_in_rank[idx] == 0) {
		idx++;
	}
    // num_in_rank[idx] != 0;
	int n_consective = 0;
	while(idx < 13 && num_in_rank[idx] != 0) {
        n_consetive++;
        idx++;
    }
    
	if (n_consective == 5) {
		straight = true;
		return;
	}

	/* 判断四张,三张,两张 */
	for (int i = 0; i < 13; i++) {
		if (num_in_rank[i] == 4) {
			four = true;
		} else if (num_in_rank[i] == 3) {
			three = true;
		} else if (num_in_rank[i] == 2) {
			pairs++;
		}
	}
}

void read_cards(void) {
    	// 初始化操作
    bool in_hand[4][13] = { false };
    
	for (int i = 0; i < 13; i++) {
		num_in_rank[i] = 0;
	}
	for (int i = 0; i < 4; i++) {
		num_in_suit[i] = 0;
	}

	// 读取5张卡牌
	int cards_read = 0;
	while (cards_read < 5) {
		bool bad_card = false;

		printf("Enter a card: ");

		char c = getchar();
		int rank;
		switch (c) {
		case '0':			exit(0);
		case '2':			rank = 0;	break;
		case '3':			rank = 1;	break;
		case '4':			rank = 2;	break;
		case '5':			rank = 3;	break;
		case '6':			rank = 4;	break;
		case '7':			rank = 5;	break;
		case '8':			rank = 6;	break;
		case '9':			rank = 7;	break;
		case 't':case 'T':	rank = 8;	break;
		case 'j':case 'J':	rank = 9;	break;
		case 'q':case 'Q':	rank = 10;	break;
		case 'k':case 'K':	rank = 11;	break;
		case 'a':case 'A':	rank = 12;	break;
		default:			bad_card = true;
		}

		c = getchar();
		int suit;
		switch (c) {
		case 'd':case 'D':	suit = 0;	break;
		case 'c':case 'C':	suit = 1;	break;
		case 'h':case 'H':	suit = 2;	break;
		case 's':case 'S':	suit = 3;	break;
		default:			bad_card = true;
		}

		// 处理这一行的剩余字符
		while ((c = getchar()) != '\n') {  
			if (c != ' ' && c != '\t')
				bad_card = true;
		}		

		if (bad_card) {
			printf("Bad card; ignored.\n");
		} else if (in_hand[suit][rank]) {
			printf("Duplicate card; ignored.\n");
		} else {
			in_hand[suit][rank] = true;
			cards_read++;
			num_in_rank[rank]++;
			num_in_suit[suit]++;
		}
	}
}

题目三:简答题(外部变量,局部变量),FIBNACCI

(a) 什么是局部变量,什么是外部变量,它们的作用域分别是什么?

(b) 存储期限有哪些?局部变量默认的存储期限是什么?怎么改变局部变量的存储期限?

(c) 请实现 next_fib() 函数,它可以输出下一个Fibonacci数列的值

long long next_fib(void) {

}

int main(void) {
	// foo();	// Fibnacii: 0, 1, 1, 2, 3, 5, 8, 13, 21, ...
	printf("next_fib() = %lld\n", next_fib());	// 1
	printf("next_fib() = %lld\n", next_fib());	// 1
	printf("next_fib() = %lld\n", next_fib());	// 2
	printf("next_fib() = %lld\n", next_fib());	// 3
	printf("next_fib() = %lld\n", next_fib());	// 5
	return 0;
}

解答:

(a),局部变量是声明在函数内部的变量,块作用域,全局变量是声明在函数外部的变量,拥有文件作用域
(b),静态存储期限和自动存储期限,寄存器存储期限,存储期限就是变量在程序运行过程中存在的时间长度。
局部变量的存储单元在函数调用时"
自动"分配,在函数返回时自动回收,即自动存储期限
可以使用static关键字将局部变量声明为静态变量。这样,变量的存储期限将变为整个程序的执行周期,而不是局部作用域内的执行周期​​​​​​​

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
long long next_fib(void) {
	static long long now = 0;
	static long long next = 1;
	long long result = now;
	now = next;
	next = result + now;
	return result;
}
int main(void) {
	
	// foo();	// Fibnacii: 0, 1, 1, 2, 3, 5, 8, 13, 21, ...
	printf("next_fib() = %lld\n", next_fib());	// 1
	printf("next_fib() = %lld\n", next_fib());	// 1
	printf("next_fib() = %lld\n", next_fib());	// 2
	printf("next_fib() = %lld\n", next_fib());	// 3
	printf("next_fib() = %lld\n", next_fib());	// 5
	printf("next_fib() = %lld\n", next_fib());	// 5
	printf("next_fib() = %lld\n", next_fib());	// 5
	printf("next_fib() = %lld\n", next_fib());	// 5
	printf("next_fib() = %lld\n", next_fib());	// 5
	printf("next_fib() = %lld\n", next_fib());	// 5

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值