1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

テトリスもどき あるいは カリグラム的プログラム

Posted at
/*cargo add getch-rs random rand*/const FW:usize=12;const FH:usize=20;const BW:usize
=4;const BS:usize=BW*BW;use getch_rs::{  Getch,Key as K};use rand::Rng;use std::sync
::{Arc,Mutex};use std::{thread as   th,     time   };fn main()->std::io::Result<()>{
let c=Arc::new(Mutex::new(Ctx::new   ())    );     println!("\x1b[2J\x1b[H\x1b[?25l"
);c.lock().unwrap().d();{let  c=Arc    ::     clone (&c);let _=th::spawn(move||{loop
{th::sleep(time::Duration    ::                 from_millis(1000));let mut c=c.lock(
).unwrap();let np=P{x:c.p                                .x,y:c.p.y+1,};if!c.collide
(&np){c.p=np;}else{ c.fix                                 ();c. el();if c.sb(){break
;}}c.d()}});}let g=   Getch              ::                  new    ();loop{match g.
getch()?{K::Left=>{                     let                          mut c=c.lock().
unwrap();let np=P{x                     :c.p                      .x.checked_sub(1).
unwrap_or(c.p.x),y:                     c.p.                       y,};c.mv(np);}K::
Right=>{let   mut c                =c    .     lock               ().   unwrap();let
np=P{x:c.p.x                    +1,y:c        .p.y,}                    ;c.mv(np);}K
::Down=>{let                 mut c=c.lock    ().unwrap(                );let np=P{x:
c.p.x,y:c.p.y              +1,};c.mv(np)    ;}K::Char(' '              )|K::Char('x'
)=>{let mut c             =c.lock().unwrap ();c.rr();}K::            Char('z')=>{let
mut c=c.lock(           ).unwrap();c.rl();}K::Esc|K::Char('q'         )=>{break;}_=>
(),}}Ok(quit(          ))}struct Ctx{f:[usize;FW*FH],p:P,bk:[        usize;BS],}impl
Ctx{fn                new()->Self{Ctx{f:[1,0,0,0,0,0,0,0,0,0,0               ,1,1,0,
0,0,0,0,             0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,             0,0,0,0,
0,0,0,0,            1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,            0,0,1,1,
0,0,0,0,0                                               ,0,0,0,0,          0,1,1,0,0
,0,0,0,0,                                                 0,0,0,0,         1,1,0,0,0
,0,0,0,0,                                                   0,0,0,1        ,1,0,0,0,
0,0,0                                                        ,0,0,0            ,0,1,
1,0,                                                         0,0,0,0            ,0,0
,0,0                                                          ,0,1,1,           0,0,
0,0,0                                                         ,0,0,0           ,0,0,
1,1,0,                                                         0,0,0           ,0,0,
0,0,0,     0,1                                                 ,1,0   ,0,0    ,0,0,0
,0,0,0    ,0,1   ,1,0,              0,0,0,0,0,0,               0,0,   0,1,    1,0,0,
0,0,      0,0,    0,0,              0,0,1,1,0,0,0              ,0,    0,0,      0,0,
0,        0,1,    1,0,              0,0,0,0,0,0,0,             0,0    ,1,1        ,0
,0         ,0     ,0,0              ,0,0,0,0,0,1,1             ,1,     1,          1
,1               ,1,1,              1,1,1,1,1,],bk            :nb()               ,p
:P::           new(),}                                        }fn d(&            mut
self)        {let mut                                        fb=self.f.        clone
();for      (p,v)in                                         self.bk.iter         ().
enumerate   (){let px=                                     p%BW;let py=p        /BW;
let         q=self.p.x                                    +px+(self.p.y+          py
)           *FW;if*v==                                    1&&q<FW*FH{fb[           q
]           =1;}}println                                   !("\x1b[H");for         (
x,          v)in fb.iter                                    ().enumerate          ()
{print      !("{}",if*                                       v==1{"#"          }else
{"."}       );if x%FW==             FW-1{                    println!          ();}}
}fn         collide(&               self,np:&P)              ->bool{for         (p,v
)in         self.bk.iter            ().enumerate              (){let             px=
p%          BW;let py=              p/BW;let q=np             .x+px+             (np
.y           +py)*FW;if             q>=FW*FH{                  continue            ;
}if          *v&self.f              [q]==1{return                true             ;}
}false                                     }fn mv                              (&mut
self,np                                    :P){if                             !self.
collide                                    (&np){                             self.p
=np;}                                      self.d                              ()}fn
fix(&                                      mut self                            ){for
(p,v                                       )in self                             .bk.
iter                                       ().                             enumerate
(){let                                     px=p%BW;                              let
py=p/BW;if                                 *v==1{self                      .f[self.p
.x+px+(self       .p.y+py)*FW]=1;}}}fn el(&mut self){for y in 1..FH       -1{let mut
can_erase          =true;for p in y*FW..(y+1)*FW{if self.f[p]==0{          can_erase
=false;             break  ;}}if can_erase{for y2 in (2..=y).              rev(){for
p in y2*                    FW..(y2+1)*FW{self.f[p]=self                    .f[p-FW]
;}}}}}fn                    sb(&mut self)->bool{self.p=P                     ::new()
;self.bk=nb()         ;if   self.collide(&self.p){self.d   ();             println!(
"Game Over!")        ;       println!("Press ESC to exit" );           return true;}
false}fn rr(&        mut     self){let mut nb:[usize;BS   ]=               Default::
default();for        p in 0  ..BS{let px=p%BW;let py=p/   BW;let      px2=py;let py2
=BW-1-px;nb[p         ]=     self.bk[px2+py2*BW];}if!self  .           collide(&self
.p){self.bk=                    nb;}self.d()}fn rl(&                   mut self){let
mut nb:[usize ;BS]=                Default::default            ();for p in 0..BS{let
px=p%BW;let py=p/BW                                              ;let px2=py;let py2
=BW-1-px;nb[px2+py2                                              *BW]=self.bk[p];}if
!self.collide(&self                                             .p){self.bk=nb;}self
.d()}}#[derive(Clone  ,Copy                                )]     struct P{x:usize,y
:usize,}impl P{fn   new()                                 ->Self {P{x:4,y:0}}}fn nb(
)->[usize;BS]{let mut rng                                  =rand::thread_rng();let p
:usize=rng.gen_range(0..7    )*16                   ;let mut r:[usize;BS]=[0;BS];for
i in 0..BS{r[i]=B[p+i];}r}   const    B      :[     usize  ;BS*7]=[0,0,0,0,0,0,0,0,1
,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,    1,1    ,0,    0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0
,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,   0,0,    0,0,   0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,0
,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0 ,0,0,1  ,0,0,1,1,1,0,0,0,0,0,];fn quit(){println!
("\x1b[?25h");}                                                                     

Windows11 + Rust 1.66.1 で動作確認。Windows のコマンドプロンプトで動作します。

[参考]
・Rustで作るテトリス風ゲーム入門
https://zenn.dev/kumavale/books/30efec2e1d3428/viewer/900eb4

エスケープシーケンスとキー入力の使い方など、非常に勉強になりました。
単なるコピペではなくフィールドやブロックのデータ構造を全く異なる形で実装しました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?