■ このスレッドは過去ログ倉庫に格納されています
暇だから麻雀のプログラムを考える
- 1 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- はい
- 2 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- 30分だけね
- 3 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- 課金したらツモが良くなる実装にしてくれ
- 4 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- プログラム?麻雀ゲームつくるってこと?
- 5 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- いまから考えるのは四槓散了と四槓子を考慮したツモです
- 6 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- >>3
そんな面倒な事はしません
- 7 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- >>4
そ
- 8 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- 手牌のスコアリングってカードゲーム全般で使い回し効きそう
- 9 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- 言語はRustで
Yamaクラスを作ります
槓をしたプレイヤーが1人なのか複数なのかを見分けるためにプレイヤーのid(0~4)を保持します
pub struct Yama {
last_kan_id: Option<u8>,
…
}
impl Yama {
pub fn kan(&mut self){}
}
- 10 :以下、?ちゃんねるからVIPがお送りします:[ここ壊れてます] .net
- >>8
麻雀の得点は複雑すぎてどうだろう…
- 11 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:41:34.408 ID:lVxD3U/BM.net
- last_kan_idには最初Noneを入れておきます
kan()メソッドではカンして嶺上牌をツモる操作を行います
ドラをめくる操作は別のメソッドに分離します
pub enum KanError {
FiveTimesKanError,
SukanError,
}
/// 戻り値は嶺上牌
pub fn kan(&mut self, player_id: u8) -> Result<PaiCode, KanError>;
- 12 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:44:05.656 ID:lVxD3U/BM.net
- Yamaクラスにはkan_countというプライベートメンバを持たせます
yamaキューにシャッフルした136枚の牌を入れておき、末尾から引く場合普通のツモを、先頭から引く場合嶺上ツモを表すものとします
- 13 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:49:14.786 ID:lVxD3U/BM.net
- ここまでのまとめ
pub struct Yama {
yama: Vec<PaiCode>,
kan_count: usize,
last_kan_id: Option<u8>,
…
}
impl Yama {
pub fn new() -> Self {
// yamaに0~135をシャッフルして入れる等
todo!()
}
pub kan(&mut self, player_id: u8) -> Result<PaiCode, KanError> {
// スマホで打つの辛すぎ
todo!()
}
}
- 14 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:53:07.990 ID:G3pmDGZ20.net
- 乱数でやれば良いだけか
将棋と違って麻雀って楽勝なんだな
底が浅いゲームだ
- 15 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:54:14.485 ID:RkwKot7u0.net
- そんなんよりAI雀士をつくれ
- 16 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:54:45.292 ID:lVxD3U/BM.net
- last_kan_idはベクタにした方がいいな…
変更
last_kan_id: Vec<u8>
このベクタのキャパシティは2とします
- 17 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:54:51.383 ID:CjeHcLxz0.net
- >>14
余裕なさすぎだろ
- 18 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:55:38.208 ID:lVxD3U/BM.net
- >>14
将棋は簡単なものは作ったが、プログラム書くのは正直麻雀の方がむずい
- 19 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:56:39.296 ID:lVxD3U/BM.net
- >>15
シャンテン数が上がるように打つだけならまぁ…
対人戦が基本だからあんまり強いAIを作る事は考えてない
- 20 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:57:00.122 ID:lVxD3U/BM.net
- 30分経ってしまった
また時間があれば戻ってきます
- 21 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:57:06.830 ID:CjeHcLxz0.net
- 容量決まってるならスライスで良さげ
- 22 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 08:58:44.577 ID:RkwKot7u0.net
- >>19
シャンテン上がるように切るだけならただの確率計算でしかないでしょ
作るのはスーパーフェニックスだよ
- 23 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 09:00:44.358 ID:HyQp2YnJ0.net
- 信じることが力さ
- 24 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 09:02:22.840 ID:MkdpUppu0.net
- 全ツしとけばVIPPERあいてならCPUが無敵だろ
- 25 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 09:07:14.553 ID:lVxD3U/BM.net
- 以下kanメソッドの中身
pub fn kan(&mut self, player_id: u8) -> Result<PaiCode, KanError> {
if self.kan_count >= 4 {
return Err(KanError::FiveTimesKanError);
}
let mut is_player_new = true;
for &p in &self.kan_player_vec {
if p == player_id {
is_player_new = false;
break;
}
}
if is_player_new {
self.kan_player_vec.push(player_id);
}
if self.kan_player_vec.len() >=2 && self.kan_count == 3 {
return Err(KanError::
書きかけですが
- 26 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 09:14:52.710 ID:CjeHcLxz0.net
- みてるよ
- 27 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 09:56:48.332 ID:lVxD3U/BM.net
- pub fn kan(&mut self, player_id: u8) -> Result<PaiCode, KanError> {
// 既に4回カンされていたら問答無用でエラー
if self.kan_count >= 4 {
return Err(KanError::FiveTimesKanError);
}
// 今回カンしたプレイヤーは初めてカンするのか?
let mut is_player_new = true;
for &p in &self.kan_player_vec {
if p == player_id {
is_player_new = false;
break;
}
}
// プレイヤーが初カンならば記録
if is_player_new {
self.kan_player_vec.push(player_id);
}
// 今回のカンを含め複数プレイヤーがカンしている
// かつ既に3回カンされているなら四槓流れ
if self.kan_player_vec.len() >= 2 && self.kan_count == 3 {
return Err(KanError::SukanError);
}
// 嶺上牌をツモる
let idx = (self.kan_count / 2) * 2 + (1 - self.kan_count % 2);
self.kan_count += 1;
Ok(self.yama[idx])
}
合ってるかな
- 28 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 09:57:12.590 ID:lVxD3U/BM.net
- >>26
あいよ
- 29 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 10:28:28.584 ID:lVxD3U/BM.net
- 次に考えるべきシチュエーションは、プレイヤーにツモを送って暗槓された場合の対処
- 30 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 10:31:21.724 ID:lVxD3U/BM.net
- 暗槓された場合、暗槓に使われた牌の種類と新たなドラ表示牌を他のプレイヤーに送る必要がある
他のプレイヤーはそれらの情報を受け取って、暗槓を受理するか、または槍槓するか(国士のみ)を選んでサーバーに送る
槍槓が不可能なプレイヤーについては返答を待たず、槍槓が可能なプレイヤーについてのみ返答を待つことにする
- 31 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 10:32:07.216 ID:3bl0ZSQG0.net
- スマホ打ちは辛すぎるだろ
- 32 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 10:32:50.374 ID:lVxD3U/BM.net
- でもパソコン持ってきてないしな
長時間電車乗ってて暇だし別に構わん
- 33 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 10:51:29.967 ID:lVxD3U/BM.net
- 一局分を管理するクラスTableがあると想定する
Tableクラスはプレイヤーとやり取りをするためのplayerインスタンスを4つ保持しているとする
Tableクラスに以下のメソッドを持たせる
/// playerは暗槓をしたプレイヤーのインデックス
/// paiは暗槓時に晒す2つの牌の牌コード
/// 戻り値は、成功時は次にツモるプレイヤーのインデックス、失敗時は失敗理由(和了、流局等)
pub fn notify_ankan(&self, player: usize, pai: [PaiCode; 2]) -> Result<usize, Fin>;
- 34 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 11:28:00.943 ID:lVxD3U/BM.net
- Playerクラスには以下のメソッドを持たせる
/// どのプレイヤーが暗槓をしたかは各プレイヤーは知っているはずなので引数では渡さない
/// 新たなドラ表示牌と暗槓時に晒される2牌を渡す
pub fn notify_ankan(&mut self, dora: PaiCode, pai: [PaiCode; 2]) -> AnkanResp;
AnkanRespは以下のように定義される
pub enum AnkanResp {
Acc,
Chankan(HoraInfo),
}
HoraInfoについては省略
役や手配、点数などを入れる
- 35 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 11:44:08.265 ID:lVxD3U/BM.net
- Playerクラスの方の実装
pub async fn notify_ankan(&self, dora: PaiCode, pai: [PaiCode; 2]) -> AnkanResp {
let packet = ServerPacket::Ankan { dora, pai };
self.send(packet);
if self.can_kokushi(pai[0]) {
let resp = self.get_response::<ClientPacket>().await;
match resp {
ClientPacket::Acc => AnkanResp::Acc,
ClientPacket::Ron => {
// HoraInfoを構築する
todo!()
AnkanResp::Chankan(hora_info)
},
_ => AnkanResp::Acc,
}
} else {
AnkanResp::Acc
}
}
- 36 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 11:45:30.568 ID:HyQp2YnJ0.net
- は
- 37 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 12:12:01.543 ID:aUzNqFi1M.net
- ミスった
さっきkan()メソッドを書いたけどカン出来るかを判定するメソッドと実際にカンをするメソッドに分けるべきだった
can_kan()とkan()に分けます
以下Tableクラスの方の実装
pub async fn notify_ankan(&mut self, player: usize, pai: [PaiCode; 2]) -> Result<usize, Fin> {
let rinshan_tsumo = self.yama.kan();
let dora = self.yama.get_dora();
let mut await_q = Vec::with_capacity(4);
for p in self.players {
await_q.push(p.notify_ankan(dora, pai));
}
let (a, b, c, d) = join!(
await_q.pop().unwrap(), await_q.pop().unwrap(),
await_q.pop().unwrap(), await_q.pop().unwrap(),
);
let mut hora_ed = Vec::with_capacity(4);
for resp in &[a, b, c, d] {
match resp {
AnkanResp::Acc => {},
AnkanResp::Chankan(hora_info) => {
hora_ed.push(hora_info.clone());
}
}
if !hora_ed.is_empty() {
return Err(Fin::Ron(hora_ed));
} else {
let is_rinshan = true;
return self.send_tsumo(player, rinshan_tsumo, is_rinshan);
}
}
- 38 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 12:21:12.225 ID:1braDTVV0.net
- とっくに30分過ぎてるけど…
- 39 :以下、?ちゃんねるからVIPがお送りします:2022/09/15(木) 12:23:30.213 ID:dUQG5oo30.net
- 乗り過ごしたか?
総レス数 39
12 KB
掲示板に戻る
全部
前100
次100
最新50
read.cgi ver.24052200