From 0db73af280f251b302062479307b68cbcc042768 Mon Sep 17 00:00:00 2001
From: FrederickPi1969 <pixinyudeyouxiang@gmail.com>
Date: Tue, 2 Feb 2021 02:23:10 -0600
Subject: [PATCH] todo - change game state

---
 .idea/.gitignore                              |   3 +
 .idea/codeStyles/Project.xml                  |   7 +
 .idea/codeStyles/codeStyleConfig.xml          |   5 +
 .idea/misc.xml                                |   6 +
 .idea/modules.xml                             |   8 +
 .idea/vcs.xml                                 |   7 +
 .../sp21-cs242-assignment1/Card.class         | Bin 0 -> 295 bytes
 .../sp21-cs242-assignment1/CardManager.class  | Bin 0 -> 3274 bytes
 .../sp21-cs242-assignment1/CardParser.class   | Bin 0 -> 3257 bytes
 .../FunctionalCard.class                      | Bin 0 -> 271 bytes
 .../sp21-cs242-assignment1/Game.class         | Bin 0 -> 2947 bytes
 .../sp21-cs242-assignment1/Main.class         | Bin 0 -> 355 bytes
 .../sp21-cs242-assignment1/NormalCard.class   | Bin 0 -> 348 bytes
 .../sp21-cs242-assignment1/Player.class       | Bin 0 -> 4874 bytes
 .../sp21-cs242-assignment1/ReverseCard.class  | Bin 0 -> 324 bytes
 .../RuleController.class                      | Bin 0 -> 2867 bytes
 .../sp21-cs242-assignment1/SkipCard.class     | Bin 0 -> 318 bytes
 .../WildDrawFourCard.class                    | Bin 0 -> 334 bytes
 .../sp21-cs242-assignment1/WirdCard.class     | Bin 0 -> 318 bytes
 sp21-cs242-assignment1.iml                    |  11 ++
 src/Card.java                                 |  51 +++++
 src/CardManager.java                          |  82 +++++++++
 src/CardParser.java                           | 116 ++++++++++++
 src/Game.java                                 | 100 ++++++++++
 src/Main.java                                 |   9 +
 src/Player.java                               | 174 ++++++++++++++++++
 src/RuleController.java                       | 105 +++++++++++
 27 files changed, 684 insertions(+)
 create mode 100644 .idea/.gitignore
 create mode 100644 .idea/codeStyles/Project.xml
 create mode 100644 .idea/codeStyles/codeStyleConfig.xml
 create mode 100644 .idea/misc.xml
 create mode 100644 .idea/modules.xml
 create mode 100644 .idea/vcs.xml
 create mode 100644 out/production/sp21-cs242-assignment1/Card.class
 create mode 100644 out/production/sp21-cs242-assignment1/CardManager.class
 create mode 100644 out/production/sp21-cs242-assignment1/CardParser.class
 create mode 100644 out/production/sp21-cs242-assignment1/FunctionalCard.class
 create mode 100644 out/production/sp21-cs242-assignment1/Game.class
 create mode 100644 out/production/sp21-cs242-assignment1/Main.class
 create mode 100644 out/production/sp21-cs242-assignment1/NormalCard.class
 create mode 100644 out/production/sp21-cs242-assignment1/Player.class
 create mode 100644 out/production/sp21-cs242-assignment1/ReverseCard.class
 create mode 100644 out/production/sp21-cs242-assignment1/RuleController.class
 create mode 100644 out/production/sp21-cs242-assignment1/SkipCard.class
 create mode 100644 out/production/sp21-cs242-assignment1/WildDrawFourCard.class
 create mode 100644 out/production/sp21-cs242-assignment1/WirdCard.class
 create mode 100644 sp21-cs242-assignment1.iml
 create mode 100644 src/Card.java
 create mode 100644 src/CardManager.java
 create mode 100644 src/CardParser.java
 create mode 100644 src/Game.java
 create mode 100644 src/Main.java
 create mode 100644 src/Player.java
 create mode 100644 src/RuleController.java

diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..eaf91e2
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..c2621b8
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,7 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <ScalaCodeStyleSettings>
+      <option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
+    </ScalaCodeStyleSettings>
+  </code_scheme>
+</component>
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..df5f35d
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
+  </state>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..2c90057
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_15" default="true" project-jdk-name="openjdk-15" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..6ac1a5f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/sp21-cs242-assignment1.iml" filepath="$PROJECT_DIR$/sp21-cs242-assignment1.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..5ebaaaf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/out/production/sp21-cs242-assignment1/Card.class b/out/production/sp21-cs242-assignment1/Card.class
new file mode 100644
index 0000000000000000000000000000000000000000..06ab6b9ad0af4a07908a8de0da93e50ff6186042
GIT binary patch
literal 295
zcmYLDK~BRk5S&e%goZ#%;RD=&19?CZ7b>Jm5gdwocU-Hu3bABT{>2H20}tR)h%q2>
z@XXG5XLmop-ai1$a8e>cT0m9EkP9YT{i5qm_nZ2@-C8pU@+;T7;aZTMov#Y)3Dk`a
zYe8mw=YwF{{D+o9aQ$Y+lwr?eE|5hG__Y;`8`s;r-BWABgKj%I)5aU!t#oiv|Cwrd
zbkCg7#5EjMF8wYTd+TCi6wS-HP@SUS@!(S!p=2f4NA<(J4mtG!RZSLhcJT&zWs%^J
V7{7rOV`BB&fC-MMco#9j@i&E8HQN9H

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/CardManager.class b/out/production/sp21-cs242-assignment1/CardManager.class
new file mode 100644
index 0000000000000000000000000000000000000000..974ab506a519a9115a45ae055c217c3654e2407b
GIT binary patch
literal 3274
zcmbtXTX)>l75<LLL}QI6aqMIg$0aC<1NJnINw@@JCo~x+FlC$zb{q(_RGyJ-#Tsdl
zG)@h)&^ACX(9%1leWDM%^nr45D6G}h=l%c||ABvymDTp!lEyPr3@`Coqa&TO&)(nu
z_T?P^`#+!j6Tl??tfL1R4ZQ~Lz!ru6tJbPD;ac9(#QBA*b~RGiGUa$qbW$NRIySE%
ztDu*xpmxCuLOal*A=8H(3=Me$Td_?cC(ARIXD!(Qw>M%z1*6j5HmP&Vb^`-qb3pVv
zmg_uk#}bZf%kmBbJ7qcF2plhJt!UV#Fc_n3MvgmiDhRB#iW5dU3JH=u28Qtsg=|$&
zQklZe$|f6#VK45|U>ewm{R-RLu9v;Yj=^iImfN(?FDev9%VUX_n4DCCItmyua1eKs
zAFEcQt<es#gu}_PD>_CorlDxyn>a+FHlC92y5!mMy--05mz#@=0(mf16FVvXO^(fr
zvBL%?a4#jD@JziCt;J!v(ubqCPs9BN9>9ZLQJh^1BfCy1zsXppL^%G$1tE1d3T&%B
znZ-j2XLS9<?f>aGj!6wu22Ow}lLV^U9I?j{b-n*1i)b8gDfRPP22SC$LT|{lh@C7C
zFk`0;oWWUzU3F{4F8N;7iY`0RGT*|;@*+~WvpZ0!QlaiK17&=hx|VFAqFXMFl;lLk
zz>JvAlA(Etza;s20~f?_E>363#`1I)Pms6UC+&o;XECQRbvvrEm{&M3w`>QtY4PXz
zrWAnb+KZ9tcxJS0n+;aOzAT<pI93a+YvP4z2Z0|PH_Kk58JS+QzF-Gty%|R40`-^;
zKV)sL+SCx2gcRl#15XP-IZBI)3N6U|cMN<N&noP0=?)hIzdr4Rf+H!!-5aEL7jIlg
zmVpISr3jh}lJN>VM$4_LYuAB<(w26`svPR9l6EDfIkarR!Bw^(7Un6}{TlHrIk>26
z@C^9UbGEkYGeL4k)wQia8r^dS0%<R~TH7&!6iF9o#*Jc=2Ef?#%{oh-6*U8<b8)kV
zG}W=M)n86dvII(gjeE9L9M3)%2WZY(kRCBm@vD|QZv~Egr<1+WvcodS$K5vV!c?Lh
z{>q%6jjZa*jMYfR`!<3_x*5<pf0~(bwjDSE-<W3ANGwAU@w#MmQR7KA&~~94*IJ{6
zZTu_3|5cvvaXg+e(RnXE7znLRIccFX(z-<um8W?s&HBxtYM+fee!oCTy+16$WK%rt
z`%xGLR%6DFmi=0|Z3}*><5zf7!>^^S{6=A<eFiw*s=s1SB>f}lG-s`9<OgiIZ*}(g
zR4`HcnB~=6I~=L_{z|hk*%8sS5p~RTZJZ-Zn}|Q%A>TSoI;K(;CChbZoycY<|DD4A
zQZoo_FEWJ#Qwq;qwn9_2`@wOZ#%0g5gOY27p&e@Yqr$;2`M#M;8vdlP_v=L&l*E4?
ztU2B<fDE5Jl%cT7uO3|Ek5$z1t;^kkYZ~Wx6XEmw{JKav#c@~h2Gpm}p1Og)51<#<
z(a+!D-(zKKd=|I~=tD0=QH~c2gL8R2&sif;ffw*%EYC|vs{VQm3>YtdiUM`-{s=?8
zQ^Wo4U$L|JA%=!O#+~apaQV7Y@Ba4-nfVy^h|vth=pHHp`e|-E25Isxjt8*=hj?)j
z!v&(xV>f<)AI1>IQwT3{tq(o7kXJXci%Y!cq=-JF2SQj~jICq*ZCrXEM+T0q<6(};
z<RhP;1aKxZHJr}8g9BWCpUepAbv*hn>|Mv>>o`ZT82#s><|4n|#h|>-CK?AWacp~3
zBz?dTpL^)fFh&@oBe)ZfbG%6Zo?%35*w1D;vf<&~ywbEhtao^rL+>qKi*BN*Z=-iS
zGEyIpa+IKEQ}BP|drwTLumIfC5w&cpP~l}fODRc;n~ZfY$4kS1L0){hOdr&HX$WVS
z7*7qqgTWRzwUb2#@tGM}7mFG4^Sv9Wof|*2j-|^RQ~$t<!uWes+#7>A%(w#g^6Lmw
z=qS_b0Y>yeUJ#D)GWQS;^ZNV<rr0=6U=}B1(DxJCD1-SUMm!@BQ~2`s<2VZn-18H%
z*~77b>wL@L6-r93Bx_O|$=WrprMa^8mRwZ}Y5BZL5gxUC3Lk4UD#rGu9yVGY&UE{B
zNPJ5&cWb=iH1oB@s7}Y&%|yut;(aON?aXk&*%RZGVoGKNXHw0ta_%+!luv<khI%B0
z^R!MVaS4U(N|k>&fC?#{*+?M@Z<x*FXE9M3{G4(<_yu0)n5FVJ`1>t>&o7;Cf52OK
H8$<sC6}<U6

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/CardParser.class b/out/production/sp21-cs242-assignment1/CardParser.class
new file mode 100644
index 0000000000000000000000000000000000000000..91bfe36bc32cfed6704cc7ea4288d3f3586384d5
GIT binary patch
literal 3257
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

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/FunctionalCard.class b/out/production/sp21-cs242-assignment1/FunctionalCard.class
new file mode 100644
index 0000000000000000000000000000000000000000..a4e16eae874d691483e7e1c6a5672e770310e5f0
GIT binary patch
literal 271
zcmY*T%MJlS5UgQX)^mM<BMy83aglJ@xU9JMt_dS+Hd(X&%Sqzk1ALU|!9^dcyQ?bI
z{e0aY0Hz3hlu-5{o2Z~FAQzPH1gbM_w4Do-2g9w0nm~J5n8fPLQ2MpVMYdA{olqOK
zE>5w^Hx#GL^ujEmbW6E*`;V0Npw9x`@IPkC0m*^PUajb)B1@J7{3t8(L@l*TtGjFC
xBV9=L;qkMs9P+zhnWqVN;h514;`)(&MkfOS8jQ`afqM&(K$}%C*I_K7`v$)1Gywnr

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/Game.class b/out/production/sp21-cs242-assignment1/Game.class
new file mode 100644
index 0000000000000000000000000000000000000000..7f3e15de9302c0b8df639fe6a9f0d75bd3d619b5
GIT binary patch
literal 2947
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
Z{EF{1XMfHAzr{!TtAUU4DSnSf{tHy)s<Hq8

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/Main.class b/out/production/sp21-cs242-assignment1/Main.class
new file mode 100644
index 0000000000000000000000000000000000000000..b12c256cfd7b300357d11523dd86ac945017b47a
GIT binary patch
literal 355
zcmZut!AiqG6r4?y#>8s174P0!1@i$BFNL1cdZ^^m(<Ux)OS*wI^}jp`9{hlQlsFp&
zMO@e!-g`6i*xi4;y#q*b7Q;g?gg-!lzQD;wKFg$*rb_OLjVfD#{*5-ey%p$9rg?}1
z0e>O2A<dcxB{0miQOn)7Q1)IHH9MoMDP^5Yt6lxw^xH@M#I($rQ@XcZ$oXWQ{p?(|
zR+}oF=A27gQ9u4?ED*1noh{W|yLFLEymleDK*;yF<3YF=5hGR!S&)OvSBRHx924Cb
kyobcWmw<f4D#9^_>^SpPr=jkzG5BTV*Wt7ij))${pPJP@<p2Nx

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/NormalCard.class b/out/production/sp21-cs242-assignment1/NormalCard.class
new file mode 100644
index 0000000000000000000000000000000000000000..c0d199f37e0e3d28ce2f7f992f7f3fd0890ee328
GIT binary patch
literal 348
zcmZWkyH3ME5S+CgJ2r-Zc~lfB6CUvg7-*1?BAwD0xxYA8ICSwzhr@qSAyM!Fd=z5O
zM53VC-I=@Dnf?0y_ykbkG=T>{LXcvBkPzHUyCQ@)s#V<`!Jka42tz`$Fm@yL?z!D=
zmW?IQoNzV~&+=8~TDI%F?5t|n#e7=1U1rq~MnbjCq8B{MrDi4*rk1*rRyn*QgYHSa
z5K{4HR1gNW(T0t({~nyFG+SFY56Uf#U9_1?f-xe#3g8Hck@OR<!X7gzqmsMNJ-&Dc
wU5fMDHwGT|xn?W@uDD(!#0*2^IACV{E5Hbcj97{z{!9JjEIgi%8F@JQ0Wz~dPXGV_

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/Player.class b/out/production/sp21-cs242-assignment1/Player.class
new file mode 100644
index 0000000000000000000000000000000000000000..78a74895f68428c4acc365e4b6f881ba2a12fb13
GIT binary patch
literal 4874
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

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/ReverseCard.class b/out/production/sp21-cs242-assignment1/ReverseCard.class
new file mode 100644
index 0000000000000000000000000000000000000000..fc60d312aacd23517ab823ac46b779f96d1751e4
GIT binary patch
literal 324
zcmZWjy-or_5dH=ZPL3acS}7<&6L|oP4GA<C3o-P=F@Yt=Ub5`*UREX+K7bEJoE1Vy
z++t?FzuEaYe0>8L;Wj}9)fiC=HPi{6Nog~03d{MJ-I7p$HrDtTLbX4b$G9Ri-()Xt
zCr3RR7fT^rr^d=_xm}2R=S8l}U0P(E&)J!PPh{lRW=CkJ7du9p&em*KGUctzJbO(i
zv!ZmFOiWnS2wy#Ic+cn|)`P<fRZoV>It{f`U>-g}AAfS9HORm{np#^&gZ8!}pmPpC
UDhj@T!R|$nPC>m^trgt-0u*{S^#A|>

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/RuleController.class b/out/production/sp21-cs242-assignment1/RuleController.class
new file mode 100644
index 0000000000000000000000000000000000000000..34888e1961552e77bf1cf5ad04da7afffd917e93
GIT binary patch
literal 2867
zcmZ`)T~ixX7=D&~>?SM?ga+IeZ0#orSQHDT0kITpi483liY>L;B`mP*lF-ejNUy!s
z@xpP2j^6Z!n>wRb=#0)dUU=n?@Gp4pjMnFzT>>fTBy;wh_k6t1`@GM2&!7MO@*995
zJc^?MAr)aA5kwU<-!mVYy^dL2>b*99&nkEdqQiF4_C^$hy3(^6G<HnKi6M?g6}pZl
z98hrJdd0EEN=45tIgaHjXf0G+*D89Wj#FB*7RE|WiPmI(_xx$kwTnwb;-F?7E#j1e
zwVSS1R^}~NENInnu+D<%^_BUOgwm#?9j_7Ws_B-6e?32Dx(icsG!(}n99GexqZ6+y
zi0@7*Xp}pIB{!}h)s;){$0+t6)$s<75o2}zxK%E=_Nr%>iV9A5?cbKZz26pRG$(YN
z#3_<iShfoHM?KG-G`+%d{X_O2k)G4gr69IuI}78kxpp>=47yeH=y(%nYI5jvOj@i5
z71Jq;`1YLVXLu+*CqTWW<8AaQXpx}gxw&%QS~4AS)Rmud%yrA<S`B9vG+Z6kFrXk@
zEEO#cgVaQMeMLi-onmDrj$yp3VnoM#xIpjzW(C@k<q4(<q`fQPx#HPQ@2KmV>v_BE
zF;y2area*j`?y3INxjsrq1&?k$dZE0iS-jYa`=E_9=|VzL69o)jBQtaxuRz+S#BIx
za8<`O;Y+iN-mK|VERpUIy^NI>=p~W2i<U3N8FSvDC7CZ3OlQ_~Z7~jvVQ<-HT+R8~
zn=nN7>@ttF7X%9mnyOsp=F)RQv65N3-{F|HLLf&a#|@R$1=F)~i}DZ!3O6Ohf*Sor
zU8`Ji7=CLV(J6=&{0kWN)>j#UTHsaX?c~Hm0gYa!J+p9s(p;6{sJKhqj>!Iwgqq6o
zzRr}!glGxF7N`2jO!=a!O%o$;t0juA1F|ypHVp5PW{{qt5uVb_v<79wPXjOEj(TLJ
z3M$D<>JF^wS@KCuvXW4BLVz`e$uA*vQm#7LF-0k9mKU<U3m~XtiQUzKMH?<SL7j|G
zmnv?-x?~HjwARYuj8Gs8i72~3m|vDH_8LSPm0uP@`DMN1w-IC+QMMm)G|6=ezwMdl
zP%=q%3o+RyWSjg^ZoJMm$)kY~+X!7m(F_&SwCMhJ%-{w`3TE+<f3)%!SI24F`U$Cy
zZ5Y`wJ4SdLN3szk66(uFjYzmJs~V9=UsekZ#4?$m5i_FOIKF{s*dHehjpN5?7L!Ri
z@Fxu|d3qb^4a76u+vpvLrD7Yn(z$`l86%o}M^0(U{!K)TD1$Q8<T+_eW(;i$$xO0;
z3yDn_oH#Eh5^{oZb0QgfDuWe)&mzUP1u;_4%Adh^;|Ogh(S|NE-A~IPulIEvCIub%
zlrO>}j-teze2!!I636j1PT)K4*u*J(kJEU@@+!z%^a%>cBUQMGTawT%%;C1o=oUW4
z9a0&?Q+&b<hKb<`z1(FY415cdwkQ#OgL(E;die?k_E^#J1s1qB28+I~L3=@<aaH_>
z6-7lx#iDH4$xsAFL-S3}z94{CuWFF{Glx?I$0x_nH9_#rr<3;Xq)Ij)qp^osVRqE;
zCc=Bz6uJY>$moyyTdL8wV~Mz>8nMh?gTx(0s3mlP4}^G30(XCNr1G2zIvJV_jdb>G
zWAq8KJ)PUQ{5!5}V{$;KEk(5%*@)0xgu0WOi&97li7gU(`gus%eDOzEWIN0Zg89<e
z_LJKIByf)T9AuE^={buFv|ZvmBr-Qa{~gS#$WoXq4$0g^xb8rZ5tT2M%~?UqL^Z~V
zAj1)i;U4ZY4u|vN68V;uAnGQB{)MXIqB8gorxX+^DF4d#@+(M+h(LZ|r$Hk3nH}GA
zDI?WOS;T6vd4#J)orq?-c`J6Ww_iOb=qe{qX!BQ9aYyk$=0<^A7fAADAX9aLl<Nc8
zQ)hf2GX!$u6+pZINTn{2*vmlf)CKaeK9GHkm;^Ha3LxU<@sY(^wVEE6tg*)aibJ=a
UW9k`Ff?{P)g2EhqCX=@QKO&tcdjJ3c

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/SkipCard.class b/out/production/sp21-cs242-assignment1/SkipCard.class
new file mode 100644
index 0000000000000000000000000000000000000000..c02cd7f71a286e5ad19fc39853c9ed34c6c78034
GIT binary patch
literal 318
zcmZWjJ8r^25Pbs<28VwEZOVKkasUtw5;PW#5&d9RVZp4Cv(CM!B2jRF94g8z5QM}Q
zGxL74^YeQ+0_dX^pn#$euZjnh2=#GpVyjcb$%wNhp)}A&+aaO&{4)1ZCX}O%-kn8n
zlr9ya5o)8R`F5eQ87~rH+F=@VGUrS?d?7u%(w~GN{9n+QXuM+cp(ealk!35<AWHKr
zR%7k<RNOzkHGeUl;LEA*xhls(WSQQjlVe`LLHm;&NOdyM!K2jb*&w|p2&iAfZ-Sif
QF4(;Z(j_R@inV~|A4Q=wTL1t6

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/WildDrawFourCard.class b/out/production/sp21-cs242-assignment1/WildDrawFourCard.class
new file mode 100644
index 0000000000000000000000000000000000000000..9e4b901ea9654b97769f1f8bc75fdb65fca62b70
GIT binary patch
literal 334
zcmZWj%}&BV5dM}{iWL!g0uGq?ljsA~c)^rQ!v#{#L%WeRWt*&9eJ)QX9(({E$~Xgr
z7~R7+JM;a_Y`#Cg03<k%(LxX*?BWP*g<jg&!kgMsH6~XowC{~I{y`zQyvieV6#5HO
zm5+|z(z<awQ8=zkt#FnZtEbI+sok8G6;B3PT~L*iGt%#ep<kI7;r<3C98s*uKIsXq
z^~{s!h<L_p3Y{9sJC=R7&-6+dBI48K3G(q^ntyj(l}xTbpx(E1%qTQ4!U<z{C*XR@
Z9nd?NZ@3fPKjXzOquLw!T9&rZ{{eBoI?Vt8

literal 0
HcmV?d00001

diff --git a/out/production/sp21-cs242-assignment1/WirdCard.class b/out/production/sp21-cs242-assignment1/WirdCard.class
new file mode 100644
index 0000000000000000000000000000000000000000..4a01bfee7641af2b98a6d1d4dd195e295e5540e0
GIT binary patch
literal 318
zcmZXOJ8r^25QhH&gNef<$qAA!fRr47hz1E7D-DR$gS`ri%v##4xffL=3J$=b5VO35
z#1`}V|8I77`^^?W56=-wD2E8@sGv${4hxewog2;uY*Rw@OB?O_gz|fP8lpz1{b-w>
z#9)x8iqML+QQyUKrtE}gnM_{dJmGB0R{Q=u4BTA*5u*6ApeJZDXY;E@yi{YyPS9wa
z7dBBt?e{$Re?AtxV!R@hQ~mQ%j)llleM%-j>HLG%M>&${WeD^rv3@d0Zb%0-uW(m7
S@4ExvZa_MNa;;cPcsc+`hBR#e

literal 0
HcmV?d00001

diff --git a/sp21-cs242-assignment1.iml b/sp21-cs242-assignment1.iml
new file mode 100644
index 0000000..9465dd8
--- /dev/null
+++ b/sp21-cs242-assignment1.iml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/src/Card.java b/src/Card.java
new file mode 100644
index 0000000..cc897fc
--- /dev/null
+++ b/src/Card.java
@@ -0,0 +1,51 @@
+import java.util.*;
+
+public abstract class Card {
+    protected String color;
+    public int cardID;
+}
+
+
+
+
+
+
+
+
+
+
+abstract class FunctionalCard extends Card {
+    abstract void changeGameState();
+
+}
+
+class SkipCard extends FunctionalCard {
+    void changeGameState() {};
+}
+
+
+class ReverseCard extends FunctionalCard {
+    void changeGameState() {};
+}
+
+
+class WirdCard extends FunctionalCard {
+    void changeGameState() {};
+}
+
+class WildDrawFourCard extends  FunctionalCard {
+    void changeGameState() {};
+}
+
+
+
+class NormalCard extends Card {
+    protected int number;
+    public NormalCard(String color, int number) {
+        color = color;
+        number = number;
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/src/CardManager.java b/src/CardManager.java
new file mode 100644
index 0000000..ee016b5
--- /dev/null
+++ b/src/CardManager.java
@@ -0,0 +1,82 @@
+import java.lang.reflect.Array;
+import java.util.*;
+
+public class CardManager {
+    private ArrayList<Integer> cardPile;
+    private ArrayList<Integer> discardPile;
+    private static CardParser parser;  // only for debug purpose...
+
+    public CardManager() {
+        parser = new CardParser();
+        initializeCardPile();
+        printCardPile();
+    }
+
+    private void initializeCardPile() {
+        cardPile = new ArrayList<Integer>();
+        for (int i = 1; i <= 108; i++) {
+            cardPile.add(i);
+        }
+        Collections.shuffle(cardPile);
+    }
+
+
+    public void printCardPile() {
+        if (!cardPile.isEmpty()) {
+            System.out.println("\n\n===================================================================");
+            System.out.println("Current Card Pile has " + cardPile.size() + " card left:");
+            for (int i = 0; i < cardPile.size(); i++) {
+                System.out.println(parser.parseCardID(cardPile.get(i)));
+            }
+            System.out.println("===================================================================\n\n");
+        } else {
+            System.out.println("============================================================");
+            System.out.println("There are no card left in the pile!");
+        }
+    }
+
+    public int numCardLeft() {
+        return cardPile.size();
+    }
+
+    /**
+     *  draw a certain number of cards from the card pile
+     * @param numToDraw total number to draw. Should be positive integer
+     * @return an arraylist of card drawn from the pile
+     */
+    public ArrayList<Integer> drawCards(int numToDraw) {
+        if (numToDraw < 0) {
+            System.out.println("drawCard error: Input number must be a positive integer");
+            return null;
+        }
+
+        ArrayList<Integer> cardsDrawnFromDiscard = new ArrayList<Integer>();
+        if (numCardLeft() < numToDraw) {
+            int numToDrawFromDiscard = numToDraw - cardPile.size();
+            cardsDrawnFromDiscard = drawCardsfromDiscardPile(numToDrawFromDiscard);
+        }
+
+        ArrayList<Integer> drawnCards = new ArrayList<Integer>(cardPile.subList(0, numToDraw));
+        drawnCards.addAll(cardsDrawnFromDiscard);
+        cardPile.subList(0, numToDraw).clear(); // erase the drawn cards
+        return drawnCards;
+    }
+
+    private ArrayList<Integer> drawCardsfromDiscardPile(int numToDraw) {
+        ArrayList<Integer> drawnCards = new ArrayList<Integer>(discardPile.subList(0, numToDraw));
+        cardPile.subList(0, numToDraw).clear(); // erase the drawn cards
+        return drawnCards;
+
+    }
+
+    /**
+     * @parm  ID of the card to be inserted
+     */
+    public void insertOneCardToDiscardPile(int cardID) {
+        discardPile.add(0, cardID);
+    }
+
+}
+
+
+
diff --git a/src/CardParser.java b/src/CardParser.java
new file mode 100644
index 0000000..b5d740b
--- /dev/null
+++ b/src/CardParser.java
@@ -0,0 +1,116 @@
+import java.util.*;
+
+class CardParser {
+    public final int NUMBER_PER_COLOR = 25;
+    public final int TOTAL_COLORS = 4;
+    public final int COLORED_CARD_NUM = NUMBER_PER_COLOR * TOTAL_COLORS;
+    public HashMap<Integer, String> colorDict;
+
+    public CardParser() {
+        colorDict = new HashMap<Integer, String>();
+        colorDict.put(0, "none");
+        colorDict.put(1, "red");
+        colorDict.put(2, "green");
+        colorDict.put(3, "blue");
+        colorDict.put(4, "yellow");
+    }
+
+
+    /**
+     * Given ID of the card, return its content as a string as "color function" - e.g. "green 1", "none wild"
+     * @param cardID a integer from 1 - 108, unique id for each card
+     * @return
+     */
+    public String parseCardID(int cardID) {
+        if (cardID < 0) {
+            // invald cardID
+            return "NA NA NA";
+        }
+
+        if (cardID > COLORED_CARD_NUM) {
+            return parseWildCard(cardID);
+        } else {
+            return parseColoredCard(cardID);
+        }
+    }
+
+    /**
+     * helper function for parse for cards without colors
+     */
+    private String parseWildCard(int cardID) {
+        if (cardID > COLORED_CARD_NUM && cardID <= COLORED_CARD_NUM + 4) {
+            return "NA sym wild";
+
+        }  else if (cardID > COLORED_CARD_NUM + 4 && cardID <= COLORED_CARD_NUM + 8) {
+            return "NA sym wildDraw4";
+        }
+        return "NA NA NA";
+    }
+
+    /**
+     * helper function for parse for cards with colors
+     */
+    private String parseColoredCard(int cardID) {
+        int colorID = (cardID - 1) / NUMBER_PER_COLOR + 1;
+        String color = colorDict.get(colorID);
+        Integer cardTypeID = cardID % NUMBER_PER_COLOR;
+
+        String type;
+        String content = "";
+        if (cardTypeID <= 18) {
+            // case 1 - 9
+            type = "num";
+            cardTypeID = cardTypeID <= 9 ? cardTypeID : (cardTypeID - 9);
+            content = cardTypeID.toString();
+
+        } else if (cardTypeID > 18 && cardTypeID <= 20) {
+            // case skip card
+            type = "sym";
+            content = "skip";
+
+        } else if (cardTypeID > 20 && cardTypeID <= 22) {
+            // case reverse card
+            type = "sym";
+            content = "reverse";
+
+        } else if (cardTypeID > 22 && cardTypeID <= 24 ) {
+            // case draw 2
+            type = "sym";
+            content = "draw2";
+
+        } else {
+            // case 0
+            type = "num";
+            content = "0";
+        }
+
+        return constructCardDescription(color, type, content);
+    }
+
+
+    private String constructCardDescription(String color, String type, String value) {
+        return color + " " + type + " " + value;
+    }
+
+    /**
+     * Given the description of one card, parse its color type and content
+     * @return a string array (String[]) : {color, type, content}
+     */
+    public String[] parseCardDescription(String description) {
+        String[] results = description.split(" ", 3);
+        String color = results[0];
+        String type = results[1];
+        String content = results[2];
+
+        String[] output = {color, type, content};
+        return output;
+    }
+
+    /**
+     * judge whether a card is a wild card - that is, whether user can decalre a color
+     * @param cardID id of card
+     */
+    public boolean isWildCard(int cardID) {
+        return cardID > COLORED_CARD_NUM;
+    }
+}
\ No newline at end of file
diff --git a/src/Game.java b/src/Game.java
new file mode 100644
index 0000000..23d3a9b
--- /dev/null
+++ b/src/Game.java
@@ -0,0 +1,100 @@
+import java.util.*;
+
+
+/**
+ * The class for recording Game state
+ * Organize the interactions among all other classes
+ */
+
+public class Game {
+    private static CardParser parser = new CardParser();
+    private static final int INIT_DRAW = 7; // every player get 7 cards at beginning
+
+    public RuleController ruler;
+    public CardManager gameCardManager;
+    public ArrayList<Player> players;
+    private int currentPlayerID; // playerID starts from 0 !!!!!
+    private boolean isClockWise = true;  // if clockwise, next player will be the element in player list
+
+
+    /**
+     * Default constructor for Game object
+     * @param playerNum
+     */
+    public Game(int playerNum) {
+        gameCardManager = new CardManager();
+        ruler = new RuleController();
+        decideFirstPlayerID(playerNum);
+
+        System.out.println("Loading player information...");
+        players = new ArrayList<Player>();
+
+        // playerID starts from 0 !!!!!
+        for (int i = 0; i < playerNum; i++) {
+            Player player = new Player(i);
+            player.drawCards(gameCardManager, INIT_DRAW);
+            players.add(player);
+        }
+    }
+
+
+    /**
+     * Randomly decide the start position of this game
+     * @param playerNum total number of players
+     */
+    private void decideFirstPlayerID(int playerNum) {
+        Random rand = new Random();
+        currentPlayerID = rand.nextInt(playerNum + 1);
+    }
+
+    /**
+     * decide the ID of next player
+     * @return ID of next player
+     */
+    private int decideNextPlayerID() {
+        if (isClockWise) {
+            return (currentPlayerID + 1) % players.size();
+        } else {
+            return (currentPlayerID - 1 + players.size()) % players.size();
+        }
+    }
+
+    /**
+     *  Run one round of UNO
+     *  very import function !
+     */
+    private void runOneRound() {
+        System.out.println("Player " + currentPlayerID + 1 + ", It's your turn!");
+        System.out.println("Please choose one card to play...");
+        Player currentPlayer = players.get(currentPlayerID);
+        int chosenCardID = currentPlayer.playCardWithCmd(this);
+        currentPlayerID = decideNextPlayerID(); // update the player for next round
+
+    }
+
+
+
+    private void changeGameState(String color, String function) {
+        // change color
+        if (color.equals("none")) {
+//            currentAllowedColor = "all";
+        }
+
+        // handle function
+        if (function.equals("skip")) {
+            currentPlayerID = decideNextPlayerID();
+
+        } else if (function.equals("draw2")) {
+            Player nextPlayer = players.get(decideNextPlayerID());
+            nextPlayer.drawCards(gameCardManager, 2);
+
+        } else if (function.equals("wildDraw4")) {
+
+        } else if (function.equals("reverse")) {
+            isClockWise = !isClockWise; // flip
+        } else if (function.equals("wild")) {
+
+        }
+    }
+
+}
diff --git a/src/Main.java b/src/Main.java
new file mode 100644
index 0000000..0003900
--- /dev/null
+++ b/src/Main.java
@@ -0,0 +1,9 @@
+public class Main {
+    public static void main(String[] args) {
+
+
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/src/Player.java b/src/Player.java
new file mode 100644
index 0000000..6a04fa1
--- /dev/null
+++ b/src/Player.java
@@ -0,0 +1,174 @@
+import java.lang.reflect.Array;
+import java.util.*;
+
+public class Player {
+    private static CardParser parser = new CardParser();
+    private ArrayList<Integer> cards;
+    public int playerID;
+
+
+    public Player(int ID) {
+        playerID = ID;
+        cards = new ArrayList<Integer>();
+    }
+
+    /**
+     * FOR CMD LINE DEBUGGING
+     * When it's this player's turn, the player must pick one card to play
+     * @return the ** cardID ** of the chosen card
+     */
+    public int playCardWithCmd(Game gameController) {
+        // instruct player to take a move
+        Scanner inputScanner = new Scanner(System.in);
+        boolean receivedValidInput = false;
+        int action = -1;
+        while (!receivedValidInput) {
+            promptChooseAction();
+            String input = inputScanner.nextLine();
+            try {
+                action = Integer.parseInt(input);
+                if (action == 1 || action == 2) {
+                    receivedValidInput = true;
+                }
+
+            } catch (Exception e) {
+                System.out.println("Please choose action from 1 or 2");
+            }
+        }
+
+        if (action == 1) {
+           return actionOneCmd(gameController);
+        } else if (action == 2){
+            return actionTwoCmd(gameController);
+        }
+
+        return -1; // user did not play valid card
+    }
+
+    private int actionOneCmd(Game gameController) {
+
+        int cardID = -1;
+        while (true) {
+            printCardsInHand();
+            System.out.println("Which card would you like to play? Please input the corresponding card number...");
+
+            int chosenCardIndex = -1;
+
+            while (chosenCardIndex < 0) {
+                chosenCardIndex = getInputtedCardIndex();
+            }
+            cardID = cards.get(chosenCardIndex);
+            if(gameController.ruler.isValidPlay(this, cardID, true)) {
+                // maintain list-cards and discardPile
+                cards.remove(chosenCardIndex);
+                gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
+                break;
+            }
+        }
+
+        if (parser.isWildCard(cardID)) {
+            // to implement
+        }
+        return cardID;
+    }
+
+    private int actionTwoCmd (Game gameController) {
+        drawCards(gameController.gameCardManager, 1); // draw new card and add it to cards in hand
+        int chosenCardIndex = cards.size() - 1;
+        int cardID = cards.get(chosenCardIndex);
+        if(gameController.ruler.isValidPlay(this, cardID, true)) {
+            cards.remove(chosenCardIndex);
+            gameController.gameCardManager.insertOneCardToDiscardPile(cardID);
+
+            if (parser.isWildCard(cardID)) {
+                // to implement
+            }
+            return cardID;
+        } else {
+            System.out.println("Sorry, the newly drawn card is not playable :(");
+            return -1;
+        }
+    }
+
+
+    /**
+     * helper function for playCardWithCommandLine
+     * parse the integer inputted by the player
+     * @return the ** INDEX ** of card in list cards that user chooses
+     */
+    public int getInputtedCardIndex() {
+        Scanner inputScanner = new Scanner(System.in);
+        String input = inputScanner.nextLine();
+        int decision;
+        try {
+            decision = Integer.parseInt(input) - 1; // -1 because we want the index in cards list
+        } catch (Exception e) {
+            System.out.println("Please input the number corresponding the card you choose!");
+            return -1;
+        }
+
+        if (decision < 0 || decision >= cards.size()) {
+            System.out.println("The card you chose does not exist!");
+            return -1;
+        }
+        return decision;
+    }
+
+
+    /**
+     * FOR real playing scenarios with GUI
+     * When it's this player's turn, the player must pick one card to play
+     */
+    public int playCardWithGUI() {
+        // not implemented yet.
+        return 0;
+    }
+
+    /**
+     *
+     * @param dealer a cardManager object that is responsible to deal cards
+     * @param numToDraw number of cards to draw
+     */
+    public void drawCards(CardManager dealer, int numToDraw) {
+        ArrayList<Integer> newCards = dealer.drawCards(numToDraw); // Initial draw
+        cards.addAll(newCards);
+    }
+
+    /**
+     * print all cards that this user has
+     */
+    public void printCardsInHand() {
+        if (!cards.isEmpty()) {
+            System.out.println("\n\n===================================================================");
+            System.out.println("Currently have " + cards.size() + " cards:");
+            for (int i = 0; i < cards.size(); i++) {
+                System.out.println("[" + (i + 1) +"]   " + parser.parseCardID(cards.get(i)));
+            }
+            System.out.println("===================================================================\n\n");
+
+        } else {
+            System.out.println("============================================================");
+            System.out.println("You got not cards in hands! Congrats, you are the winner!");
+        }
+    }
+
+    /**
+     * getter for cards (private attribute for tracking all cards owned by a player)
+     * @return
+     */
+    public ArrayList<Integer> getCards() {
+        return cards;
+    }
+
+
+    /**
+     * prompt player to take action current round
+     */
+    private void promptChooseAction() {
+        printCardsInHand();
+        System.out.println("Please choose you action this round:");
+        System.out.println("[1] Play a owned card");
+        System.out.println("[2] Draw a card and play it if possible");
+    }
+
+}
\ No newline at end of file
diff --git a/src/RuleController.java b/src/RuleController.java
new file mode 100644
index 0000000..2447ccc
--- /dev/null
+++ b/src/RuleController.java
@@ -0,0 +1,105 @@
+import java.util.ArrayList;
+
+public class RuleController {
+    private static CardParser parser = new CardParser();
+    private String currentAllowedColor = "all";
+    private String currentAllowedNumber = "all";
+    private String currentAllowedSymbol = "all";
+
+
+    /**
+     * Given a card played by the user, judge whether this play is valid
+     * that is, all cards must be played following the rule
+     * @return whether the play is valid
+     */
+    public boolean isValidPlay(Player player, int cardID, boolean updateIfValid) {
+
+        String cardDescription = parser.parseCardID(cardID);
+        String[] result = parser.parseCardDescription(cardDescription);
+        String color = result[0];
+        String type = result[1];
+        String content = result[2];
+        boolean valid = false;
+
+        if (checkAttrMatch(currentAllowedColor, color))
+            valid = true;
+        if (checkAttrMatch(currentAllowedNumber, content) || checkAttrMatch(currentAllowedSymbol, content))
+            valid = true;
+        if (content.equals("wildDraw4")) {
+            valid = checkDraw4IsLegal(player);
+        }
+
+        if (valid && updateIfValid) {
+            currentAllowedColor = color.equals("NA") ? "none" : color; // wildcard played
+            if (type.equals("sym")) {
+                currentAllowedSymbol = content;
+                currentAllowedNumber = "none";
+            } else if (type.equals("num")) {
+                currentAllowedNumber = content;
+                currentAllowedSymbol = "none";
+            }
+        }
+        return false;
+    }
+
+    private boolean checkAttrMatch(String legalString, String stringToCheck) {
+        return legalString.equals("all") || stringToCheck.equals(legalString);
+    }
+
+    /**
+     * Check whether a player have currently allowed color when attempting to play wild draw 4
+     */
+    private boolean checkDraw4IsLegal(Player player) {
+        ArrayList<Integer> cards = player.getCards();
+        for (int i = 0; i < cards.size(); i++) {
+            int cardID = cards.get(i);
+            String cardDescription = parser.parseCardID(cardID);
+            String color = parser.parseCardDescription(cardDescription)[0];
+            if (color.equals(currentAllowedNumber)) return false;
+        }
+        return true;
+    }
+
+    /**
+     *  Getter and Setter for Allowed number
+     */
+
+    public String getAllowedNumber() {
+        return currentAllowedNumber;
+    }
+
+    public void getAllowedNumber(String number) {
+        currentAllowedColor = number;
+    }
+
+    /**
+     *  Getter and Setter for Allowed Symbol
+     */
+
+    public String getCurrentAllowedSymbol() {
+        return currentAllowedSymbol;
+    }
+
+    public void setAllowedSymbol(String symbol) {
+        currentAllowedSymbol = symbol;
+    }
+
+
+    /**
+     *  Getter and Setter for Allowed Color
+     */
+
+    public String getAllowedColor() {
+        return currentAllowedColor;
+    }
+
+    public void setAllowedColor(String color) {
+        currentAllowedColor = color;
+    }
+
+}
+
+
+
+
+
-- 
GitLab