實現在控制臺斗地主
今天給大家一起分享一下,最近回頭學習java基礎實現的一個控制臺版的斗地主。先給大家簡單看一下要求:
有地主,有2個農民,地主有額外3張牌。
游戲開始時,顯示地主的牌,并從控制臺接收要出的牌,地主出牌后。
農民1顯示牌,并從控制臺接收要出的牌,以此類推。
如果地主贏了,提示地主勝利。如果有一個農民勝利了,就提示農民勝利。
1.先理清邏輯
在開始敲代碼之前,我們第一步一定不是急著動手。而是需要分析一下,我們做的這個項目,它一步一步的應該怎么來操作和完成。理清思路之后,其實剩下的就都是水到渠成的了!初學的同學不信可以先不看下面的分析,來直接寫這個項目。我相信中間你肯定是會遇到問題的。
好,那我們在看到題目之后,進行簡單的分析。
- 需要創建一個牌類(poke),它有牌號(pokecard)、花色(pokecolor)這兩個基本屬性,因為這兩個屬性是固定不改變的,所以在定義的時候我們可以把它們用final修飾符修飾。其次它還需要一個生成一副牌的方法makepoke(),以便于之后調用。隨后我們還需要有一個排序的方法,來進行一個從大到小的顯示,也方便在發牌之后重新進行排序。這里就還有一個自定義的比較器接口mycomparator。
- 需要創建一個人物類(person),它有一副牌(poke)、人名(name)、是否是地主(islandlord)這三個基本屬性有一個出牌的方法(sendpoke)。
- 需要創建一個斗地主的工具類(fightlandlords),它有牌(poke)、人(person)兩個基本屬性。 有一個選地主的方法(changelandlord)、一個洗牌的方法(shufflecards)、一個發牌的方法(licensing)、一個打牌的方法(startpoke)。
按照思路一步步實現
我們先實現牌類,具體代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package com.dun.palypoke; import java.util.arraylist; import java.util.collections; /* 牌類 有牌號、花色兩個屬性; 有生成一副牌(54張牌)的方法; 實現比較器接口,便于整理牌時從小到大排序。 構造方法私有化,只能通過生成一副牌方法來獲得牌。 */ public class poke{ private static final string[] pokecard = {“3”, “4”, “5”, “6”, “7”, “8”, “9”, “10”, “j”, “q”, “k”, “a”, “2”, “小王”, “大王”}; //牌號 private static final string[] pokecolor = {“♠”, “♥”, “♣”, “♦”}; // 牌的花色 public string[] getpokecard() { return pokecard; } public string[] getpokecolor() { return pokecolor; } private poke() { } /* 生成牌的方法, 返回一副牌 */ public static arraylist makepoke() { arraylist poke = new arraylist<>(); for (int i = 0; i < pokecard.length - 2; i++) { for (int j = 0; j < pokecolor.length; j++) { collections.addall(poke, pokecolor[j] + pokecard[i]); } } /* 手動添加大小王 */ poke.add(pokecard[pokecard.length - 2 ]); poke.add(pokecard[pokecard.length - 1 ]); return poke; } } |
在makepoke()方法中,我使用了兩層for循環,第一個用來控制牌號,第二個用來控制花色,因為大小王不涉及到花色,所以我在最后一步進行手動的添加。最后將這副牌返回。因為我的構造方法設置為私有,所以我將makepoke方法加入了static修飾詞,這樣只能通過類名點的方式調用。
新建一個test測試類,測試一下。
看到運行完成,我們的第一個類就完成了!
隨后我們編寫第二個類——人物類。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
package com.dun.palypoke; import java.util.arraylist; import java.util.iterator; import java.util.scanner; /* 創建人物類: 1.有一副牌(集合/數組)、名字、是否是地主三個屬性; 2.有出牌的方法,出牌前先在控制臺打印出所有的牌,再從控制臺接受出的牌,并出牌。 3.有理牌的方法,整理后牌按從小到大方式排序。 */ public class person { private arraylist poke = new arraylist(); //一副牌 private string name; //名稱 private boolean islandlord; //是否是地主 public scanner sc = new scanner(system.in); public arraylist getpoke() { return poke; } public person() { } public person(string name){ this.name = name; } public void setpoke(arraylist poke) { this.poke = poke; } public string getname() { return name; } public void setname(string name) { this.name = name; } public boolean isislandlord() { return islandlord; } public void setislandlord(boolean islandlord) { this.islandlord = islandlord; } /* 出牌 局部變量list的作用是當用戶出多張牌時,通過n++來表示用戶出的牌和他手上的牌是否全部存在,如果存在,就全部刪除。 */ public arraylist sendpoke(arraylist poke){ system.out.println(poke); arraylist list = new arraylist<>(); //臨時變量 for ( int i = 0 ; i < poke.size(); i++) { list.add(poke.get(i)); } system.out.println( "請輸入要出的牌(不用輸入花色,出多張牌用,分開、要不起或不要請輸入n):" ); string usersc = sc.next(); if (usersc.equalsignorecase( "n" )){ system.out.println( "要不起" ); return this .poke; } string[] spoke = usersc.split( "," ); int n = 0 ; //計數 int i = 0 ; while (i<spoke.length) { iterator iterator = list.iterator(); while (iterator.hasnext()){ string next = (string) iterator.next(); if (next.contains(spoke[i])){ iterator.remove(); i = 0 ; n++; break ; } } i++; } if (n == spoke.length){ this .poke = list; system.out.println( "出牌成功" ); } else { system.out.println( "你沒有這些牌,給我這渾水摸魚呢?" ); } return this .poke; } } |
人物類定義完基本屬性后,添加get、set方法之后我們就只需要進行出牌方法(sendpoke)的編寫了
這里一開始我把poke給打印了一遍,因為斗地主工具類我們還沒有編寫,所以這里打印出來的poke集合肯定是整副牌,不過不用擔心,等我們把工具類寫完之后,這里訪問的poke就是其中一個用戶的牌了。
我定義了一個臨時變量,用來進行刪除操作,因為涉及到出多張牌的情況,如何不定義這個臨時變量,用用戶自己的牌去進行刪除操作,就會出現異常。比如,**用戶出3個6帶一個4,可是用戶的牌只有三個六,我在查找到這3個六之后已經把它刪除了,后面的4沒有找到,雖然也是會輸出”你沒有這些牌,給我這渾水摸魚呢?",但是用戶的牌中的三個六我卻已經給它刪除了。這很顯然不符合我們的邏輯。**所以我定義了臨時的一個集合變量。只有當將用戶輸入的所有數都遍歷完了之后,通過n 的 值是否與spoke.length相等來將list的值重新賦值給 poke 。這樣就完美的解決了這個問題!
在test類中測試,可以看到,我們的人物類(person)也完成咯!
最后我們來完成斗地主的工具類(fightlandlord):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
package com.dun.palypoke; import java.util.arraylist; import java.util.collections; import java.util.random; /* 斗地主類 1.有牌(集合)和人(集合)兩個屬性;有一個構造方法,構造方法要傳入3個人,一副牌; 2.有洗牌的方法,用于重排所有的牌。 3.有發牌的方法,為3個用戶按順序發牌,同時地主獲得最后3張牌。 4.有開始方法,開始后地主先出牌,農1出牌,農2出牌....如果地主牌先出完,打印地主勝利;如果農民有一個人先勝利,則打印農民勝利。 */ public class fightlandlords { public arraylist poke ; //獲取一副牌 public person p1; //人1 public person p2; //人2 public person p3; //人3 public fightlandlords(arraylist poke, person p1,person p2,person p3) { this.poke = poke; this.p1 = p1; this.p2 = p2; this.p3 = p3; } /* 選地主 */ public void changelandlord(){ random random = new random(); int n = random.nextint(3)+1; if(n == 1){ system.out.println(p1.getname()+"成為地主"); p1.setislandlord(true); }else if(n == 2){ system.out.println(p2.getname()+"成為地主"); p2.setislandlord(true); } else{ system.out.println(p3.getname()+"成為地主"); p3.setislandlord(true); } } /* 洗牌 */ public arraylist shufflecards(){ collections.shuffle(poke); return poke; } /* 發牌 */ public void licensing() { changelandlord(); if (p1.isislandlord()){ p1.getpoke().add(poke.get(poke.size()-3)); p1.getpoke().add(poke.get(poke.size()-2)); p1.getpoke().add(poke.get(poke.size()-1)); } if (p2.isislandlord()){ p2.getpoke().add(poke.get(poke.size()-3)); p2.getpoke().add(poke.get(poke.size()-2)); p2.getpoke().add(poke.get(poke.size()-1)); } if (p3.isislandlord()){ p3.getpoke().add(poke.get(poke.size()-3)); p3.getpoke().add(poke.get(poke.size()-2)); p3.getpoke().add(poke.get(poke.size()-1)); } for (int i = 0; i < poke.size() - 3; i += 3) { if (p1.isislandlord()) { p1.getpoke().add(poke.get(i)); p2.getpoke().add(poke.get(i + 1)); p3.getpoke().add(poke.get(i + 2)); } if(p2.isislandlord()){ p2.getpoke().add(poke.get(i)); p3.getpoke().add(poke.get(i+1)); p1.getpoke().add(poke.get(i+2)); } if(p3.isislandlord()){ p3.getpoke().add(poke.get(i)); p1.getpoke().add(poke.get(i+1)); p2.getpoke().add(poke.get(i+2)); } } /* 從小到大排序 */ collections.sort(p1.getpoke(),new mycomparator()); collections.sort(p2.getpoke(),new mycomparator()); collections.sort(p3.getpoke(),new mycomparator()); } /* 開始打牌 */ public void startpoke(){ if (p1.isislandlord()){ while ( true ){ system.out.print( "地主出牌:" ); p1.sendpoke(p1.getpoke()); if (p1.getpoke().size() == 0 ){ system.out.println( "地主勝利" ); break ; } system.out.print( "農民一出牌:" ); p2.sendpoke(p2.getpoke()); if (p2.getpoke().size() == 0 || p3.getpoke().size() == 0 ){ system.out.println( "農民勝利" ); break ; } system.out.print( "農民二出牌:" ); p3.sendpoke(p3.getpoke()); if (p2.getpoke().size() == 0 || p3.getpoke().size() == 0 ){ system.out.println( "農民勝利" ); break ; } } } if (p2.isislandlord()){ while ( true ){ system.out.print( "地主出牌:" ); p2.sendpoke(p2.getpoke()); if (p2.getpoke().size() == 0 ){ system.out.println( "地主勝利" ); break ; } system.out.print( "農民一出牌:" ); p3.sendpoke(p3.getpoke()); if (p1.getpoke().size() == 0 || p3.getpoke().size() == 0 ){ system.out.println( "農民勝利" ); break ; } system.out.print( "農民二出牌:" ); p1.sendpoke(p1.getpoke()); if (p1.getpoke().size() == 0 || p3.getpoke().size() == 0 ){ system.out.println( "農民勝利" ); break ; } } } if (p3.isislandlord()){ while ( true ){ system.out.print( "地主出牌:" ); p3.sendpoke(p1.getpoke()); if (p3.getpoke().size() == 0 ){ system.out.println( "地主勝利" ); break ; } system.out.print( "農民一出牌:" ); p1.sendpoke(p1.getpoke()); if (p2.getpoke().size() == 0 || p1.getpoke().size() == 0 ){ system.out.println( "農民勝利" ); break ; } system.out.print( "農民二出牌:" ); p2.sendpoke(p2.getpoke()); if (p2.getpoke().size() == 0 || p1.getpoke().size() == 0 ){ system.out.println( "農民勝利" ); break ; } } } } } |
給大家一一解釋一下這些方法,第一個很簡單,changelandlord()通過創建一個1-3的隨機數來選擇地主,并將值傳給對應人物的setislandlord方法!
第二個洗牌,我直接調用了collections的api中的shuffle方法,它可以幫我們完成隨機排序,大家也可以自己寫,這個shuffle方法的底層邏輯也是通過創建隨機數來實現了!我這個偷了一下懶。哈哈~
第三個發牌,我先把地主選出來。然后先把屬性地主的最后三張牌發給他,隨后通過for循環給三個玩家依次發牌,發完一輪之后i+3。最后的collections.sort方法中,將每個玩家的牌按照我們平時斗地主,3最小,2最大,a比2小的方法通過mycomparator()進行了重寫。這是我比較器的源碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package com.dun.palypoke; import java.util.comparator; /* 自定義排序方法 */ public class mycomparator implements comparator<string> { @override public int compare(string o1, string o2) { char m = 0 ,n = 0 ; if (o1.charat( 1 ) == '2' ){ m = 'm' ; } else if (o1.charat( 1 ) == '1' ){ m = ':' ; } else if (o1.charat( 1 ) == 'j' ){ m = 'i' ; } else if (o1.charat( 1 ) == 'q' ){ m = 'j' ; } else if (o1.charat( 1 ) == 'a' ){ m = 'l' ; } else if (o1.charat( 0 ) == '大' ){ m = 'o' ; } else if (o1.charat( 0 ) == '小' ){ m = 'n' ; } else { m = o1.charat( 1 ); } if (o2.charat( 1 ) == '2' ){ n = 'm' ; } else if (o2.charat( 1 ) == '1' ){ n = ':' ; } else if (o2.charat( 1 ) == 'j' ){ n = 'i' ; } else if (o2.charat( 1 ) == 'q' ){ n = 'j' ; } else if (o2.charat( 1 ) == 'a' ){ n = 'l' ; } else if (o2.charat( 0 ) == '大' ){ n = 'o' ; } else if (o2.charat( 0 ) == '小' ){ n = 'n' ; } else { n = o2.charat( 1 ); } return m - n; } } |
主要比較它們第一個字符的ascill碼表,因為除了大小王,其他牌下標0表示的是花色,所以比較下標的第一位。
這樣我們整個項目就完成咯。給大家看看運行的效果~
好咯,咱們項目就寫到這兒,中間是還有一些小細節的。大家有問題的可以在評論區聯系我哈。這個項目用數組也是可以做的哈。
到此這篇關于java實現輕輕松松控制臺斗地主的文章就介紹到這了,更多相關java 控制臺斗地主內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/weixin_45053664/article/details/115871346